OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/win/worker_process_launcher.h" | 5 #include "remoting/host/win/worker_process_launcher.h" |
6 | 6 |
7 #include "base/location.h" | |
7 #include "base/logging.h" | 8 #include "base/logging.h" |
8 #include "base/single_thread_task_runner.h" | 9 #include "base/single_thread_task_runner.h" |
9 #include "base/time.h" | 10 #include "base/time.h" |
10 #include "base/timer.h" | 11 #include "base/timer.h" |
11 #include "base/win/object_watcher.h" | 12 #include "base/win/object_watcher.h" |
12 #include "base/win/windows_version.h" | 13 #include "base/win/windows_version.h" |
13 #include "ipc/ipc_listener.h" | 14 #include "ipc/ipc_listener.h" |
14 #include "ipc/ipc_message.h" | 15 #include "ipc/ipc_message.h" |
15 #include "net/base/backoff_entry.h" | 16 #include "net/base/backoff_entry.h" |
17 #include "remoting/host/chromoting_messages.h" | |
16 #include "remoting/host/worker_process_ipc_delegate.h" | 18 #include "remoting/host/worker_process_ipc_delegate.h" |
17 | 19 |
18 using base::TimeDelta; | 20 using base::TimeDelta; |
19 using base::win::ScopedHandle; | 21 using base::win::ScopedHandle; |
20 | 22 |
21 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { | 23 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { |
22 // Number of initial errors (in sequence) to ignore before applying | 24 // Number of initial errors (in sequence) to ignore before applying |
23 // exponential back-off rules. | 25 // exponential back-off rules. |
24 0, | 26 0, |
25 | 27 |
(...skipping 11 matching lines...) Expand all Loading... | |
37 60000, | 39 60000, |
38 | 40 |
39 // Time to keep an entry from being discarded even when it | 41 // Time to keep an entry from being discarded even when it |
40 // has no significant state, -1 to never discard. | 42 // has no significant state, -1 to never discard. |
41 -1, | 43 -1, |
42 | 44 |
43 // Don't use initial delay unless the last request was an error. | 45 // Don't use initial delay unless the last request was an error. |
44 false, | 46 false, |
45 }; | 47 }; |
46 | 48 |
49 const int kDelayTimeoutSeconds = 5; | |
Wez
2013/03/07 01:54:35
nit: Naming. e.g. kCrashRequestTimeoutSeconds?
Wez
2013/03/07 01:54:35
5s is probably too short for many systems, BTW.
alexeypa (please no reviews)
2013/03/07 21:28:30
Done.
alexeypa (please no reviews)
2013/03/07 21:28:30
It is enough because the timeout is, strictly spea
Wez
2013/03/08 01:45:15
Right, but if the timeout is short then on slower,
| |
47 | 50 |
48 namespace remoting { | 51 namespace remoting { |
49 | 52 |
50 // Launches a worker process that is controlled via an IPC channel. All | 53 // Launches a worker process that is controlled via an IPC channel. All |
51 // interaction with the spawned process is through the IPC::Listener and Send() | 54 // interaction with the spawned process is through the IPC::Listener and Send() |
52 // method. In case of error the channel is closed and the worker process is | 55 // method. In case of error the channel is closed and the worker process is |
53 // terminated. | 56 // terminated. |
54 class WorkerProcessLauncher::Core | 57 class WorkerProcessLauncher::Core |
55 : public base::RefCountedThreadSafe<WorkerProcessLauncher::Core>, | 58 : public base::RefCountedThreadSafe<Core, Core>, |
56 public base::win::ObjectWatcher::Delegate, | 59 public base::win::ObjectWatcher::Delegate, |
57 public IPC::Listener { | 60 public IPC::Listener { |
58 public: | 61 public: |
59 // Creates the launcher that will use |launcher_delegate| to manage the worker | 62 // Creates the launcher that will use |launcher_delegate| to manage the worker |
60 // process and |worker_delegate| to handle IPCs. The caller must ensure that | 63 // process and |worker_delegate| to handle IPCs. The caller must ensure that |
61 // |worker_delegate| remains valid until Stoppable::Stop() method has been | 64 // |worker_delegate| remains valid until Stoppable::Stop() method has been |
62 // called. | 65 // called. |
63 // | 66 // |
64 // The caller should call all the methods on this class on | 67 // The caller should call all the methods on this class on |
65 // the |caller_task_runner| thread. Methods of both delegate interfaces are | 68 // the |caller_task_runner| thread. Methods of both delegate interfaces are |
66 // called on the |caller_task_runner| thread as well. | 69 // called on the |caller_task_runner| thread as well. |
67 Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 70 Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
68 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, | 71 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, |
69 WorkerProcessIpcDelegate* worker_delegate); | 72 WorkerProcessIpcDelegate* worker_delegate); |
70 | 73 |
71 // Launches the worker process. | 74 // Launches the worker process. |
72 void Start(); | 75 void Start(); |
73 | 76 |
74 // Stops the worker process asynchronously. The caller can drop the reference | 77 // Stops the worker process asynchronously. The caller can drop the reference |
75 // to |this| as soon as Stop() returns. | 78 // to |this| as soon as Stop() returns. |
76 void Stop(); | 79 void Stop(); |
77 | 80 |
78 // Sends an IPC message to the worker process. The message will be silently | 81 // See WorkerProcessLauncher::Crash(). |
79 // dropped if Send() is called before Start() or after stutdown has been | 82 void Crash(const tracked_objects::Location& location); |
80 // initiated. | 83 |
84 // See WorkerProcessLauncher::Send(). | |
81 void Send(IPC::Message* message); | 85 void Send(IPC::Message* message); |
82 | 86 |
83 // base::win::ObjectWatcher::Delegate implementation. | 87 // base::win::ObjectWatcher::Delegate implementation. |
84 virtual void OnObjectSignaled(HANDLE object) OVERRIDE; | 88 virtual void OnObjectSignaled(HANDLE object) OVERRIDE; |
85 | 89 |
86 // IPC::Listener implementation. | 90 // IPC::Listener implementation. |
87 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; | 91 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; |
88 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; | 92 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; |
89 virtual void OnChannelError() OVERRIDE; | 93 virtual void OnChannelError() OVERRIDE; |
90 | 94 |
95 // Destroys |Core| instances on the |caller_task_runner_| thread. This is | |
96 // needed because base::OneShotTimer instances must be destroyed on the same | |
97 // thread they were created on. | |
98 static void Destruct(const Core* core); | |
Wez
2013/03/07 01:54:35
We use an explicit separate struct e.g. CoreTraits
alexeypa (please no reviews)
2013/03/07 21:28:30
WorkerProcessLauncher::Core is a private class dec
Wez
2013/03/08 01:45:15
Surely the friend declaration would be in the Core
alexeypa (please no reviews)
2013/03/08 17:43:19
No, there will be one in WorkerProcessLauncher and
| |
99 | |
91 private: | 100 private: |
92 friend class base::RefCountedThreadSafe<Core>; | 101 friend class base::DeleteHelper<Core>; |
93 virtual ~Core(); | 102 virtual ~Core(); |
94 | 103 |
95 // Attempts to launch the worker process. Schedules next launch attempt if | 104 // Attempts to launch the worker process. Schedules next launch attempt if |
96 // creation of the process fails. | 105 // creation of the process fails. |
97 void LaunchWorker(); | 106 void LaunchWorker(); |
98 | 107 |
99 // Records a successful launch attempt. | 108 // Records a successful launch attempt. |
100 void RecordSuccessfulLaunch(); | 109 void RecordSuccessfulLaunch(); |
101 | 110 |
102 // Stops the worker process asynchronously and schedules next launch attempt | 111 // Stops the worker process asynchronously and schedules next launch attempt |
103 // unless Stop() has been called already. | 112 // unless Stop() has been called already. |
104 void StopWorker(); | 113 void StopWorker(); |
105 | 114 |
106 // All public methods are called on the |caller_task_runner| thread. | 115 // All public methods are called on the |caller_task_runner| thread. |
107 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; | 116 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; |
108 | 117 |
109 // Implements specifics of launching a worker process. | 118 // Implements specifics of launching a worker process. |
110 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate_; | 119 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate_; |
111 | 120 |
112 // Handles IPC messages sent by the worker process. | 121 // Handles IPC messages sent by the worker process. |
113 WorkerProcessIpcDelegate* worker_delegate_; | 122 WorkerProcessIpcDelegate* worker_delegate_; |
114 | 123 |
115 // Pointer to GetNamedPipeClientProcessId() API if it is available. | 124 // Pointer to GetNamedPipeClientProcessId() API if it is available. |
116 typedef BOOL (WINAPI * GetNamedPipeClientProcessIdFn)(HANDLE, DWORD*); | 125 typedef BOOL (WINAPI * GetNamedPipeClientProcessIdFn)(HANDLE, DWORD*); |
117 GetNamedPipeClientProcessIdFn get_named_pipe_client_pid_; | 126 GetNamedPipeClientProcessIdFn get_named_pipe_client_pid_; |
118 | 127 |
128 // The timer used to delay termination of the worker process when an IPC error | |
129 // occured or when Crash() request is pending | |
130 base::OneShotTimer<Core> delay_timer_; | |
Wez
2013/03/07 01:54:35
nit: Naming.
alexeypa (please no reviews)
2013/03/07 21:28:30
Done.
| |
131 | |
119 // True if IPC messages should be passed to |worker_delegate_|. | 132 // True if IPC messages should be passed to |worker_delegate_|. |
120 bool ipc_enabled_; | 133 bool ipc_enabled_; |
121 | 134 |
122 // The timer used to delay termination of the process in the case of an IPC | |
123 // error. | |
124 scoped_ptr<base::OneShotTimer<Core> > ipc_error_timer_; | |
125 | |
126 // Launch backoff state. | 135 // Launch backoff state. |
127 net::BackoffEntry launch_backoff_; | 136 net::BackoffEntry launch_backoff_; |
128 | 137 |
129 // Timer used to delay recording a successfull launch. | 138 // Timer used to delay recording a successfull launch. |
130 scoped_ptr<base::OneShotTimer<Core> > launch_success_timer_; | 139 base::OneShotTimer<Core> launch_success_timer_; |
131 | 140 |
132 // Timer used to schedule the next attempt to launch the process. | 141 // Timer used to schedule the next attempt to launch the process. |
133 scoped_ptr<base::OneShotTimer<Core> > launch_timer_; | 142 base::OneShotTimer<Core> launch_timer_; |
134 | 143 |
135 // Used to determine when the launched process terminates. | 144 // Used to determine when the launched process terminates. |
136 base::win::ObjectWatcher process_watcher_; | 145 base::win::ObjectWatcher process_watcher_; |
137 | 146 |
138 // A waiting handle that becomes signalled once the launched process has | 147 // A waiting handle that becomes signalled once the launched process has |
139 // been terminated. | 148 // been terminated. |
140 ScopedHandle process_exit_event_; | 149 ScopedHandle process_exit_event_; |
141 | 150 |
142 // True when Stop() has been called. | 151 // True when Stop() has been called. |
143 bool stopping_; | 152 bool stopping_; |
144 | 153 |
145 DISALLOW_COPY_AND_ASSIGN(Core); | 154 DISALLOW_COPY_AND_ASSIGN(Core); |
146 }; | 155 }; |
147 | 156 |
148 WorkerProcessLauncher::Delegate::~Delegate() { | 157 WorkerProcessLauncher::Delegate::~Delegate() { |
149 } | 158 } |
150 | 159 |
151 WorkerProcessLauncher::Core::Core( | 160 WorkerProcessLauncher::Core::Core( |
152 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 161 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
153 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, | 162 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, |
154 WorkerProcessIpcDelegate* worker_delegate) | 163 WorkerProcessIpcDelegate* worker_delegate) |
155 : caller_task_runner_(caller_task_runner), | 164 : caller_task_runner_(caller_task_runner), |
156 launcher_delegate_(launcher_delegate.Pass()), | 165 launcher_delegate_(launcher_delegate.Pass()), |
157 worker_delegate_(worker_delegate), | 166 worker_delegate_(worker_delegate), |
158 get_named_pipe_client_pid_(NULL), | 167 get_named_pipe_client_pid_(NULL), |
159 ipc_enabled_(false), | 168 ipc_enabled_(false), |
160 launch_backoff_(&kDefaultBackoffPolicy), | 169 launch_backoff_(&kDefaultBackoffPolicy), |
161 stopping_(false) { | 170 stopping_(false) { |
162 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 171 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
163 | |
164 // base::OneShotTimer must be destroyed on the same thread it was created on. | |
165 ipc_error_timer_.reset(new base::OneShotTimer<Core>()); | |
166 launch_success_timer_.reset(new base::OneShotTimer<Core>()); | |
167 launch_timer_.reset(new base::OneShotTimer<Core>()); | |
168 } | 172 } |
169 | 173 |
170 void WorkerProcessLauncher::Core::Start() { | 174 void WorkerProcessLauncher::Core::Start() { |
171 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 175 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
172 DCHECK(!stopping_); | 176 DCHECK(!stopping_); |
173 | 177 |
174 LaunchWorker(); | 178 LaunchWorker(); |
175 } | 179 } |
176 | 180 |
177 void WorkerProcessLauncher::Core::Stop() { | 181 void WorkerProcessLauncher::Core::Stop() { |
178 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 182 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
179 | 183 |
180 if (!stopping_) { | 184 if (!stopping_) { |
181 stopping_ = true; | 185 stopping_ = true; |
182 worker_delegate_ = NULL; | 186 worker_delegate_ = NULL; |
183 StopWorker(); | 187 StopWorker(); |
184 } | 188 } |
185 } | 189 } |
186 | 190 |
191 void WorkerProcessLauncher::Core::Crash( | |
192 const tracked_objects::Location& location) { | |
193 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | |
194 | |
195 // Ask the worker process to crash voluntarily if it is still connected. | |
196 if (ipc_enabled_) { | |
197 Send(new ChromotingDaemonMsg_Crash(location.function_name(), | |
198 location.file_name(), | |
199 location.line_number())); | |
200 } | |
201 | |
202 // Close the channel and ignore any not yet processed messages. | |
203 launcher_delegate_->CloseChannel(); | |
204 ipc_enabled_ = false; | |
205 | |
206 // Give the worker process some time to crash. | |
207 if (!delay_timer_.IsRunning()) { | |
208 delay_timer_.Start(FROM_HERE, | |
209 base::TimeDelta::FromSeconds(kDelayTimeoutSeconds), this, | |
210 &Core::StopWorker); | |
Wez
2013/03/07 01:54:35
StopWorker "stops the worker asynchronously". Is i
alexeypa (please no reviews)
2013/03/07 21:28:30
It is tougher than Chuck Norris (as long as we are
| |
211 } | |
212 } | |
213 | |
187 void WorkerProcessLauncher::Core::Send(IPC::Message* message) { | 214 void WorkerProcessLauncher::Core::Send(IPC::Message* message) { |
188 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 215 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
189 | 216 |
190 if (ipc_enabled_) { | 217 if (ipc_enabled_) { |
191 launcher_delegate_->Send(message); | 218 launcher_delegate_->Send(message); |
192 } else { | 219 } else { |
193 delete message; | 220 delete message; |
194 } | 221 } |
195 } | 222 } |
196 | 223 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 } | 261 } |
235 | 262 |
236 void WorkerProcessLauncher::Core::OnChannelError() { | 263 void WorkerProcessLauncher::Core::OnChannelError() { |
237 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 264 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
238 | 265 |
239 // Schedule a delayed termination of the worker process. Usually, the pipe is | 266 // Schedule a delayed termination of the worker process. Usually, the pipe is |
240 // disconnected when the worker process is about to exit. Waiting a little bit | 267 // disconnected when the worker process is about to exit. Waiting a little bit |
241 // here allows the worker to exit completely and so, notify | 268 // here allows the worker to exit completely and so, notify |
242 // |process_watcher_|. As the result KillProcess() will not be called and | 269 // |process_watcher_|. As the result KillProcess() will not be called and |
243 // the original exit code reported by the worker process will be retrieved. | 270 // the original exit code reported by the worker process will be retrieved. |
244 ipc_error_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(5), | 271 if (!delay_timer_.IsRunning()) { |
245 this, &Core::StopWorker); | 272 delay_timer_.Start(FROM_HERE, |
273 base::TimeDelta::FromSeconds(kDelayTimeoutSeconds), this, | |
274 &Core::StopWorker); | |
275 } | |
276 } | |
277 | |
278 // static | |
279 void WorkerProcessLauncher::Core::Destruct(const Core* core) { | |
280 core->caller_task_runner_->DeleteSoon(FROM_HERE, core); | |
246 } | 281 } |
247 | 282 |
248 WorkerProcessLauncher::Core::~Core() { | 283 WorkerProcessLauncher::Core::~Core() { |
284 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | |
249 DCHECK(stopping_); | 285 DCHECK(stopping_); |
250 } | 286 } |
251 | 287 |
252 void WorkerProcessLauncher::Core::LaunchWorker() { | 288 void WorkerProcessLauncher::Core::LaunchWorker() { |
253 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 289 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
254 DCHECK(!ipc_enabled_); | 290 DCHECK(!ipc_enabled_); |
255 DCHECK(!launch_success_timer_->IsRunning()); | 291 DCHECK(!launch_success_timer_.IsRunning()); |
256 DCHECK(!launch_timer_->IsRunning()); | 292 DCHECK(!launch_timer_.IsRunning()); |
257 DCHECK(!process_exit_event_.IsValid()); | 293 DCHECK(!process_exit_event_.IsValid()); |
258 DCHECK(process_watcher_.GetWatchedObject() == NULL); | 294 DCHECK(process_watcher_.GetWatchedObject() == NULL); |
259 | 295 |
260 // Launch the process and attach an object watcher to the returned process | 296 // Launch the process and attach an object watcher to the returned process |
261 // handle so that we get notified if the process terminates. | 297 // handle so that we get notified if the process terminates. |
262 if (launcher_delegate_->LaunchProcess(this, &process_exit_event_)) { | 298 if (launcher_delegate_->LaunchProcess(this, &process_exit_event_)) { |
263 if (process_watcher_.StartWatching(process_exit_event_, this)) { | 299 if (process_watcher_.StartWatching(process_exit_event_, this)) { |
264 ipc_enabled_ = true; | 300 ipc_enabled_ = true; |
265 // Record a successful launch once the process has been running for at | 301 // Record a successful launch once the process has been running for at |
266 // least two seconds. | 302 // least two seconds. |
267 launch_success_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(2), | 303 launch_success_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(2), |
268 this, &Core::RecordSuccessfulLaunch); | 304 this, &Core::RecordSuccessfulLaunch); |
269 return; | 305 return; |
270 } | 306 } |
271 | 307 |
272 launcher_delegate_->KillProcess(CONTROL_C_EXIT); | 308 launcher_delegate_->KillProcess(CONTROL_C_EXIT); |
273 } | 309 } |
274 | 310 |
275 launch_backoff_.InformOfRequest(false); | 311 launch_backoff_.InformOfRequest(false); |
276 StopWorker(); | 312 StopWorker(); |
277 } | 313 } |
278 | 314 |
279 void WorkerProcessLauncher::Core::RecordSuccessfulLaunch() { | 315 void WorkerProcessLauncher::Core::RecordSuccessfulLaunch() { |
280 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 316 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
281 | 317 |
282 launch_backoff_.InformOfRequest(true); | 318 launch_backoff_.InformOfRequest(true); |
283 } | 319 } |
284 | 320 |
285 void WorkerProcessLauncher::Core::StopWorker() { | 321 void WorkerProcessLauncher::Core::StopWorker() { |
286 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 322 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
287 | 323 |
288 // Keep the object alive in case one of delegates decides to delete |this|. | 324 // Keep the object alive in case one of delegates decides to delete |this|. |
289 scoped_refptr<Core> self = this; | 325 scoped_refptr<Core> self = this; |
290 | 326 |
291 // Record a launch failure if the process exited too soon. | 327 // Record a launch failure if the process exited too soon. |
292 if (launch_success_timer_->IsRunning()) { | 328 if (launch_success_timer_.IsRunning()) { |
293 launch_success_timer_->Stop(); | 329 launch_success_timer_.Stop(); |
294 launch_backoff_.InformOfRequest(false); | 330 launch_backoff_.InformOfRequest(false); |
295 } | 331 } |
296 | 332 |
297 // Ignore any remaining IPC messages. | 333 // Ignore any remaining IPC messages. |
298 ipc_enabled_ = false; | 334 ipc_enabled_ = false; |
299 | 335 |
300 // Kill the process if it has been started already. | 336 // Kill the process if it has been started already. |
301 if (process_watcher_.GetWatchedObject() != NULL) { | 337 if (process_watcher_.GetWatchedObject() != NULL) { |
302 launcher_delegate_->KillProcess(CONTROL_C_EXIT); | 338 launcher_delegate_->KillProcess(CONTROL_C_EXIT); |
303 | 339 |
304 // Wait until the process is actually stopped if the caller keeps | 340 // Wait until the process is actually stopped if the caller keeps |
305 // a reference to |this|. Otherwise terminate everything right now - there | 341 // a reference to |this|. Otherwise terminate everything right now - there |
306 // won't be a second chance. | 342 // won't be a second chance. |
307 if (!stopping_) | 343 if (!stopping_) |
308 return; | 344 return; |
309 | 345 |
310 process_watcher_.StopWatching(); | 346 process_watcher_.StopWatching(); |
311 } | 347 } |
312 | 348 |
313 ipc_error_timer_->Stop(); | 349 delay_timer_.Stop(); |
314 process_exit_event_.Close(); | 350 process_exit_event_.Close(); |
315 | 351 |
316 // Do not relaunch the worker process if the caller has asked us to stop. | 352 // Do not relaunch the worker process if the caller has asked us to stop. |
317 if (stopping_) { | 353 if (stopping_) |
318 ipc_error_timer_.reset(); | |
319 launch_timer_.reset(); | |
320 return; | 354 return; |
321 } | |
322 | 355 |
323 if (launcher_delegate_->IsPermanentError(launch_backoff_.failure_count())) { | 356 if (launcher_delegate_->IsPermanentError(launch_backoff_.failure_count())) { |
324 if (!stopping_) | 357 if (!stopping_) |
325 worker_delegate_->OnPermanentError(); | 358 worker_delegate_->OnPermanentError(); |
326 } else { | 359 } else { |
327 // Schedule the next attempt to launch the worker process. | 360 // Schedule the next attempt to launch the worker process. |
328 launch_timer_->Start(FROM_HERE, launch_backoff_.GetTimeUntilRelease(), | 361 launch_timer_.Start(FROM_HERE, launch_backoff_.GetTimeUntilRelease(), this, |
329 this, &Core::LaunchWorker); | 362 &Core::LaunchWorker); |
330 } | 363 } |
331 } | 364 } |
332 | 365 |
333 WorkerProcessLauncher::WorkerProcessLauncher( | 366 WorkerProcessLauncher::WorkerProcessLauncher( |
334 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 367 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
335 scoped_ptr<Delegate> launcher_delegate, | 368 scoped_ptr<Delegate> launcher_delegate, |
336 WorkerProcessIpcDelegate* worker_delegate) { | 369 WorkerProcessIpcDelegate* worker_delegate) { |
337 core_ = new Core(caller_task_runner, launcher_delegate.Pass(), | 370 core_ = new Core(caller_task_runner, launcher_delegate.Pass(), |
338 worker_delegate); | 371 worker_delegate); |
339 core_->Start(); | 372 core_->Start(); |
340 } | 373 } |
341 | 374 |
342 WorkerProcessLauncher::~WorkerProcessLauncher() { | 375 WorkerProcessLauncher::~WorkerProcessLauncher() { |
343 core_->Stop(); | 376 core_->Stop(); |
344 core_ = NULL; | 377 core_ = NULL; |
345 } | 378 } |
346 | 379 |
380 void WorkerProcessLauncher::Crash(const tracked_objects::Location& location) { | |
381 core_->Crash(location); | |
382 } | |
383 | |
347 void WorkerProcessLauncher::Send(IPC::Message* message) { | 384 void WorkerProcessLauncher::Send(IPC::Message* message) { |
348 core_->Send(message); | 385 core_->Send(message); |
349 } | 386 } |
350 | 387 |
351 } // namespace remoting | 388 } // namespace remoting |
OLD | NEW |