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 kKillProcessTimeoutSeconds = 5; |
| 50 const int kLaunchSuccessTimeoutSeconds = 2; |
47 | 51 |
48 namespace remoting { | 52 namespace remoting { |
49 | 53 |
50 // Launches a worker process that is controlled via an IPC channel. All | 54 // 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() | 55 // 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 | 56 // method. In case of error the channel is closed and the worker process is |
53 // terminated. | 57 // terminated. |
54 class WorkerProcessLauncher::Core | 58 class WorkerProcessLauncher::Core |
55 : public base::RefCountedThreadSafe<WorkerProcessLauncher::Core>, | 59 : public base::RefCountedThreadSafe<Core, Core>, |
56 public base::win::ObjectWatcher::Delegate, | 60 public base::win::ObjectWatcher::Delegate, |
57 public IPC::Listener { | 61 public IPC::Listener { |
58 public: | 62 public: |
59 // Creates the launcher that will use |launcher_delegate| to manage the worker | 63 // 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 | 64 // process and |worker_delegate| to handle IPCs. The caller must ensure that |
61 // |worker_delegate| remains valid until Stoppable::Stop() method has been | 65 // |worker_delegate| remains valid until Stoppable::Stop() method has been |
62 // called. | 66 // called. |
63 // | 67 // |
64 // The caller should call all the methods on this class on | 68 // The caller should call all the methods on this class on |
65 // the |caller_task_runner| thread. Methods of both delegate interfaces are | 69 // the |caller_task_runner| thread. Methods of both delegate interfaces are |
66 // called on the |caller_task_runner| thread as well. | 70 // called on the |caller_task_runner| thread as well. |
67 Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 71 Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
68 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, | 72 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, |
69 WorkerProcessIpcDelegate* worker_delegate); | 73 WorkerProcessIpcDelegate* worker_delegate); |
70 | 74 |
71 // Launches the worker process. | 75 // Launches the worker process. |
72 void Start(); | 76 void Start(); |
73 | 77 |
74 // Stops the worker process asynchronously. The caller can drop the reference | 78 // Stops the worker process asynchronously. The caller can drop the reference |
75 // to |this| as soon as Stop() returns. | 79 // to |this| as soon as Stop() returns. |
76 void Stop(); | 80 void Stop(); |
77 | 81 |
78 // Sends an IPC message to the worker process. The message will be silently | 82 // See WorkerProcessLauncher::Crash(). |
79 // dropped if Send() is called before Start() or after stutdown has been | 83 void Crash(const tracked_objects::Location& location); |
80 // initiated. | 84 |
| 85 // See WorkerProcessLauncher::Send(). |
81 void Send(IPC::Message* message); | 86 void Send(IPC::Message* message); |
82 | 87 |
| 88 // Used to emulate |launch_success_timer_| expiration. |
| 89 void ResetLaunchSuccessTimeoutForTest(); |
| 90 |
| 91 // Set the desired timeout for |kill_process_timer_|. |
| 92 void SetKillProcessTimeoutForTest(const base::TimeDelta& timeout); |
| 93 |
83 // base::win::ObjectWatcher::Delegate implementation. | 94 // base::win::ObjectWatcher::Delegate implementation. |
84 virtual void OnObjectSignaled(HANDLE object) OVERRIDE; | 95 virtual void OnObjectSignaled(HANDLE object) OVERRIDE; |
85 | 96 |
86 // IPC::Listener implementation. | 97 // IPC::Listener implementation. |
87 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; | 98 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; |
88 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; | 99 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; |
89 virtual void OnChannelError() OVERRIDE; | 100 virtual void OnChannelError() OVERRIDE; |
90 | 101 |
| 102 // Destroys |Core| instances on the |caller_task_runner_| thread. This is |
| 103 // needed because base::OneShotTimer instances must be destroyed on the same |
| 104 // thread they were created on. |
| 105 static void Destruct(const Core* core); |
| 106 |
91 private: | 107 private: |
92 friend class base::RefCountedThreadSafe<Core>; | 108 friend class base::DeleteHelper<Core>; |
93 virtual ~Core(); | 109 virtual ~Core(); |
94 | 110 |
95 // Attempts to launch the worker process. Schedules next launch attempt if | 111 // Attempts to launch the worker process. Schedules next launch attempt if |
96 // creation of the process fails. | 112 // creation of the process fails. |
97 void LaunchWorker(); | 113 void LaunchWorker(); |
98 | 114 |
99 // Records a successful launch attempt. | 115 // Records a successful launch attempt. |
100 void RecordSuccessfulLaunch(); | 116 void RecordSuccessfulLaunch(); |
101 | 117 |
102 // Stops the worker process asynchronously and schedules next launch attempt | 118 // Stops the worker process asynchronously and schedules next launch attempt |
103 // unless Stop() has been called already. | 119 // unless Stop() has been called already. |
104 void StopWorker(); | 120 void StopWorker(); |
105 | 121 |
106 // All public methods are called on the |caller_task_runner| thread. | 122 // All public methods are called on the |caller_task_runner| thread. |
107 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; | 123 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; |
108 | 124 |
109 // Implements specifics of launching a worker process. | 125 // Implements specifics of launching a worker process. |
110 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate_; | 126 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate_; |
111 | 127 |
112 // Handles IPC messages sent by the worker process. | 128 // Handles IPC messages sent by the worker process. |
113 WorkerProcessIpcDelegate* worker_delegate_; | 129 WorkerProcessIpcDelegate* worker_delegate_; |
114 | 130 |
115 // Pointer to GetNamedPipeClientProcessId() API if it is available. | 131 // Pointer to GetNamedPipeClientProcessId() API if it is available. |
116 typedef BOOL (WINAPI * GetNamedPipeClientProcessIdFn)(HANDLE, DWORD*); | 132 typedef BOOL (WINAPI * GetNamedPipeClientProcessIdFn)(HANDLE, DWORD*); |
117 GetNamedPipeClientProcessIdFn get_named_pipe_client_pid_; | 133 GetNamedPipeClientProcessIdFn get_named_pipe_client_pid_; |
118 | 134 |
119 // True if IPC messages should be passed to |worker_delegate_|. | 135 // True if IPC messages should be passed to |worker_delegate_|. |
120 bool ipc_enabled_; | 136 bool ipc_enabled_; |
121 | 137 |
122 // The timer used to delay termination of the process in the case of an IPC | 138 // The timer used to delay termination of the worker process when an IPC error |
123 // error. | 139 // occured or when Crash() request is pending |
124 scoped_ptr<base::OneShotTimer<Core> > ipc_error_timer_; | 140 base::OneShotTimer<Core> kill_process_timer_; |
| 141 |
| 142 // The default timeout for |kill_process_timer_|. |
| 143 base::TimeDelta kill_process_timeout_; |
125 | 144 |
126 // Launch backoff state. | 145 // Launch backoff state. |
127 net::BackoffEntry launch_backoff_; | 146 net::BackoffEntry launch_backoff_; |
128 | 147 |
129 // Timer used to delay recording a successfull launch. | 148 // Timer used to delay recording a successfull launch. |
130 scoped_ptr<base::OneShotTimer<Core> > launch_success_timer_; | 149 base::OneShotTimer<Core> launch_success_timer_; |
131 | 150 |
132 // Timer used to schedule the next attempt to launch the process. | 151 // Timer used to schedule the next attempt to launch the process. |
133 scoped_ptr<base::OneShotTimer<Core> > launch_timer_; | 152 base::OneShotTimer<Core> launch_timer_; |
134 | 153 |
135 // Used to determine when the launched process terminates. | 154 // Used to determine when the launched process terminates. |
136 base::win::ObjectWatcher process_watcher_; | 155 base::win::ObjectWatcher process_watcher_; |
137 | 156 |
138 // A waiting handle that becomes signalled once the launched process has | 157 // A waiting handle that becomes signalled once the launched process has |
139 // been terminated. | 158 // been terminated. |
140 ScopedHandle process_exit_event_; | 159 ScopedHandle process_exit_event_; |
141 | 160 |
142 // True when Stop() has been called. | 161 // True when Stop() has been called. |
143 bool stopping_; | 162 bool stopping_; |
144 | 163 |
145 DISALLOW_COPY_AND_ASSIGN(Core); | 164 DISALLOW_COPY_AND_ASSIGN(Core); |
146 }; | 165 }; |
147 | 166 |
148 WorkerProcessLauncher::Delegate::~Delegate() { | 167 WorkerProcessLauncher::Delegate::~Delegate() { |
149 } | 168 } |
150 | 169 |
151 WorkerProcessLauncher::Core::Core( | 170 WorkerProcessLauncher::Core::Core( |
152 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 171 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
153 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, | 172 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, |
154 WorkerProcessIpcDelegate* worker_delegate) | 173 WorkerProcessIpcDelegate* worker_delegate) |
155 : caller_task_runner_(caller_task_runner), | 174 : caller_task_runner_(caller_task_runner), |
156 launcher_delegate_(launcher_delegate.Pass()), | 175 launcher_delegate_(launcher_delegate.Pass()), |
157 worker_delegate_(worker_delegate), | 176 worker_delegate_(worker_delegate), |
158 get_named_pipe_client_pid_(NULL), | 177 get_named_pipe_client_pid_(NULL), |
159 ipc_enabled_(false), | 178 ipc_enabled_(false), |
| 179 kill_process_timeout_( |
| 180 base::TimeDelta::FromSeconds(kKillProcessTimeoutSeconds)), |
160 launch_backoff_(&kDefaultBackoffPolicy), | 181 launch_backoff_(&kDefaultBackoffPolicy), |
161 stopping_(false) { | 182 stopping_(false) { |
162 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 183 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 } | 184 } |
169 | 185 |
170 void WorkerProcessLauncher::Core::Start() { | 186 void WorkerProcessLauncher::Core::Start() { |
171 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 187 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
172 DCHECK(!stopping_); | 188 DCHECK(!stopping_); |
173 | 189 |
174 LaunchWorker(); | 190 LaunchWorker(); |
175 } | 191 } |
176 | 192 |
177 void WorkerProcessLauncher::Core::Stop() { | 193 void WorkerProcessLauncher::Core::Stop() { |
178 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 194 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
179 | 195 |
180 if (!stopping_) { | 196 if (!stopping_) { |
181 stopping_ = true; | 197 stopping_ = true; |
182 worker_delegate_ = NULL; | 198 worker_delegate_ = NULL; |
183 StopWorker(); | 199 StopWorker(); |
184 } | 200 } |
185 } | 201 } |
186 | 202 |
| 203 void WorkerProcessLauncher::Core::Crash( |
| 204 const tracked_objects::Location& location) { |
| 205 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 206 |
| 207 // Ask the worker process to crash voluntarily if it is still connected. |
| 208 if (ipc_enabled_) { |
| 209 Send(new ChromotingDaemonMsg_Crash(location.function_name(), |
| 210 location.file_name(), |
| 211 location.line_number())); |
| 212 } |
| 213 |
| 214 // Close the channel and ignore any not yet processed messages. |
| 215 launcher_delegate_->CloseChannel(); |
| 216 ipc_enabled_ = false; |
| 217 |
| 218 // Give the worker process some time to crash. |
| 219 if (!kill_process_timer_.IsRunning()) { |
| 220 kill_process_timer_.Start(FROM_HERE, kill_process_timeout_, this, |
| 221 &Core::StopWorker); |
| 222 } |
| 223 } |
| 224 |
187 void WorkerProcessLauncher::Core::Send(IPC::Message* message) { | 225 void WorkerProcessLauncher::Core::Send(IPC::Message* message) { |
188 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 226 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
189 | 227 |
190 if (ipc_enabled_) { | 228 if (ipc_enabled_) { |
191 launcher_delegate_->Send(message); | 229 launcher_delegate_->Send(message); |
192 } else { | 230 } else { |
193 delete message; | 231 delete message; |
194 } | 232 } |
195 } | 233 } |
196 | 234 |
| 235 void WorkerProcessLauncher::Core::ResetLaunchSuccessTimeoutForTest() { |
| 236 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 237 |
| 238 if (launch_success_timer_.IsRunning()) { |
| 239 launch_success_timer_.Stop(); |
| 240 RecordSuccessfulLaunch(); |
| 241 } |
| 242 } |
| 243 |
| 244 void WorkerProcessLauncher::Core::SetKillProcessTimeoutForTest( |
| 245 const base::TimeDelta& timeout) { |
| 246 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 247 |
| 248 kill_process_timeout_ = timeout; |
| 249 } |
| 250 |
197 void WorkerProcessLauncher::Core::OnObjectSignaled(HANDLE object) { | 251 void WorkerProcessLauncher::Core::OnObjectSignaled(HANDLE object) { |
198 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 252 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
199 DCHECK(process_watcher_.GetWatchedObject() == NULL); | 253 DCHECK(process_watcher_.GetWatchedObject() == NULL); |
200 | 254 |
201 StopWorker(); | 255 StopWorker(); |
202 } | 256 } |
203 | 257 |
204 bool WorkerProcessLauncher::Core::OnMessageReceived( | 258 bool WorkerProcessLauncher::Core::OnMessageReceived( |
205 const IPC::Message& message) { | 259 const IPC::Message& message) { |
206 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 260 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
(...skipping 27 matching lines...) Expand all Loading... |
234 } | 288 } |
235 | 289 |
236 void WorkerProcessLauncher::Core::OnChannelError() { | 290 void WorkerProcessLauncher::Core::OnChannelError() { |
237 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 291 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
238 | 292 |
239 // Schedule a delayed termination of the worker process. Usually, the pipe is | 293 // 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 | 294 // disconnected when the worker process is about to exit. Waiting a little bit |
241 // here allows the worker to exit completely and so, notify | 295 // here allows the worker to exit completely and so, notify |
242 // |process_watcher_|. As the result KillProcess() will not be called and | 296 // |process_watcher_|. As the result KillProcess() will not be called and |
243 // the original exit code reported by the worker process will be retrieved. | 297 // the original exit code reported by the worker process will be retrieved. |
244 ipc_error_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(5), | 298 if (!kill_process_timer_.IsRunning()) { |
245 this, &Core::StopWorker); | 299 kill_process_timer_.Start(FROM_HERE, kill_process_timeout_, this, |
| 300 &Core::StopWorker); |
| 301 } |
| 302 } |
| 303 |
| 304 // static |
| 305 void WorkerProcessLauncher::Core::Destruct(const Core* core) { |
| 306 core->caller_task_runner_->DeleteSoon(FROM_HERE, core); |
246 } | 307 } |
247 | 308 |
248 WorkerProcessLauncher::Core::~Core() { | 309 WorkerProcessLauncher::Core::~Core() { |
| 310 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
249 DCHECK(stopping_); | 311 DCHECK(stopping_); |
250 } | 312 } |
251 | 313 |
252 void WorkerProcessLauncher::Core::LaunchWorker() { | 314 void WorkerProcessLauncher::Core::LaunchWorker() { |
253 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 315 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
254 DCHECK(!ipc_enabled_); | 316 DCHECK(!ipc_enabled_); |
255 DCHECK(!launch_success_timer_->IsRunning()); | 317 DCHECK(!launch_success_timer_.IsRunning()); |
256 DCHECK(!launch_timer_->IsRunning()); | 318 DCHECK(!launch_timer_.IsRunning()); |
257 DCHECK(!process_exit_event_.IsValid()); | 319 DCHECK(!process_exit_event_.IsValid()); |
258 DCHECK(process_watcher_.GetWatchedObject() == NULL); | 320 DCHECK(process_watcher_.GetWatchedObject() == NULL); |
259 | 321 |
260 // Launch the process and attach an object watcher to the returned process | 322 // Launch the process and attach an object watcher to the returned process |
261 // handle so that we get notified if the process terminates. | 323 // handle so that we get notified if the process terminates. |
262 if (launcher_delegate_->LaunchProcess(this, &process_exit_event_)) { | 324 if (launcher_delegate_->LaunchProcess(this, &process_exit_event_)) { |
263 if (process_watcher_.StartWatching(process_exit_event_, this)) { | 325 if (process_watcher_.StartWatching(process_exit_event_, this)) { |
264 ipc_enabled_ = true; | 326 ipc_enabled_ = true; |
265 // Record a successful launch once the process has been running for at | 327 // Record a successful launch once the process has been running for at |
266 // least two seconds. | 328 // least two seconds. |
267 launch_success_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(2), | 329 launch_success_timer_.Start( |
268 this, &Core::RecordSuccessfulLaunch); | 330 FROM_HERE, base::TimeDelta::FromSeconds(kLaunchSuccessTimeoutSeconds), |
| 331 this, &Core::RecordSuccessfulLaunch); |
269 return; | 332 return; |
270 } | 333 } |
271 | 334 |
272 launcher_delegate_->KillProcess(CONTROL_C_EXIT); | 335 launcher_delegate_->KillProcess(CONTROL_C_EXIT); |
273 } | 336 } |
274 | 337 |
275 launch_backoff_.InformOfRequest(false); | 338 launch_backoff_.InformOfRequest(false); |
276 StopWorker(); | 339 StopWorker(); |
277 } | 340 } |
278 | 341 |
279 void WorkerProcessLauncher::Core::RecordSuccessfulLaunch() { | 342 void WorkerProcessLauncher::Core::RecordSuccessfulLaunch() { |
280 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 343 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
281 | 344 |
282 launch_backoff_.InformOfRequest(true); | 345 launch_backoff_.InformOfRequest(true); |
283 } | 346 } |
284 | 347 |
285 void WorkerProcessLauncher::Core::StopWorker() { | 348 void WorkerProcessLauncher::Core::StopWorker() { |
286 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 349 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
287 | 350 |
288 // Keep the object alive in case one of delegates decides to delete |this|. | 351 // Keep the object alive in case one of delegates decides to delete |this|. |
289 scoped_refptr<Core> self = this; | 352 scoped_refptr<Core> self = this; |
290 | 353 |
291 // Record a launch failure if the process exited too soon. | 354 // Record a launch failure if the process exited too soon. |
292 if (launch_success_timer_->IsRunning()) { | 355 if (launch_success_timer_.IsRunning()) { |
293 launch_success_timer_->Stop(); | 356 launch_success_timer_.Stop(); |
294 launch_backoff_.InformOfRequest(false); | 357 launch_backoff_.InformOfRequest(false); |
295 } | 358 } |
296 | 359 |
297 // Ignore any remaining IPC messages. | 360 // Ignore any remaining IPC messages. |
298 ipc_enabled_ = false; | 361 ipc_enabled_ = false; |
299 | 362 |
300 // Kill the process if it has been started already. | 363 // Kill the process if it has been started already. |
301 if (process_watcher_.GetWatchedObject() != NULL) { | 364 if (process_watcher_.GetWatchedObject() != NULL) { |
302 launcher_delegate_->KillProcess(CONTROL_C_EXIT); | 365 launcher_delegate_->KillProcess(CONTROL_C_EXIT); |
303 | 366 |
304 // Wait until the process is actually stopped if the caller keeps | 367 // Wait until the process is actually stopped if the caller keeps |
305 // a reference to |this|. Otherwise terminate everything right now - there | 368 // a reference to |this|. Otherwise terminate everything right now - there |
306 // won't be a second chance. | 369 // won't be a second chance. |
307 if (!stopping_) | 370 if (!stopping_) |
308 return; | 371 return; |
309 | 372 |
310 process_watcher_.StopWatching(); | 373 process_watcher_.StopWatching(); |
311 } | 374 } |
312 | 375 |
313 ipc_error_timer_->Stop(); | 376 kill_process_timer_.Stop(); |
314 process_exit_event_.Close(); | 377 process_exit_event_.Close(); |
315 | 378 |
316 // Do not relaunch the worker process if the caller has asked us to stop. | 379 // Do not relaunch the worker process if the caller has asked us to stop. |
317 if (stopping_) { | 380 if (stopping_) |
318 ipc_error_timer_.reset(); | |
319 launch_timer_.reset(); | |
320 return; | 381 return; |
321 } | |
322 | 382 |
323 if (launcher_delegate_->IsPermanentError(launch_backoff_.failure_count())) { | 383 if (launcher_delegate_->IsPermanentError(launch_backoff_.failure_count())) { |
324 if (!stopping_) | 384 if (!stopping_) |
325 worker_delegate_->OnPermanentError(); | 385 worker_delegate_->OnPermanentError(); |
326 } else { | 386 } else { |
327 // Schedule the next attempt to launch the worker process. | 387 // Schedule the next attempt to launch the worker process. |
328 launch_timer_->Start(FROM_HERE, launch_backoff_.GetTimeUntilRelease(), | 388 launch_timer_.Start(FROM_HERE, launch_backoff_.GetTimeUntilRelease(), this, |
329 this, &Core::LaunchWorker); | 389 &Core::LaunchWorker); |
330 } | 390 } |
331 } | 391 } |
332 | 392 |
333 WorkerProcessLauncher::WorkerProcessLauncher( | 393 WorkerProcessLauncher::WorkerProcessLauncher( |
334 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 394 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
335 scoped_ptr<Delegate> launcher_delegate, | 395 scoped_ptr<Delegate> launcher_delegate, |
336 WorkerProcessIpcDelegate* worker_delegate) { | 396 WorkerProcessIpcDelegate* worker_delegate) { |
337 core_ = new Core(caller_task_runner, launcher_delegate.Pass(), | 397 core_ = new Core(caller_task_runner, launcher_delegate.Pass(), |
338 worker_delegate); | 398 worker_delegate); |
339 core_->Start(); | 399 core_->Start(); |
340 } | 400 } |
341 | 401 |
342 WorkerProcessLauncher::~WorkerProcessLauncher() { | 402 WorkerProcessLauncher::~WorkerProcessLauncher() { |
343 core_->Stop(); | 403 core_->Stop(); |
344 core_ = NULL; | 404 core_ = NULL; |
345 } | 405 } |
346 | 406 |
| 407 void WorkerProcessLauncher::Crash(const tracked_objects::Location& location) { |
| 408 core_->Crash(location); |
| 409 } |
| 410 |
347 void WorkerProcessLauncher::Send(IPC::Message* message) { | 411 void WorkerProcessLauncher::Send(IPC::Message* message) { |
348 core_->Send(message); | 412 core_->Send(message); |
349 } | 413 } |
350 | 414 |
| 415 void WorkerProcessLauncher::ResetLaunchSuccessTimeoutForTest() { |
| 416 core_->ResetLaunchSuccessTimeoutForTest(); |
| 417 } |
| 418 |
| 419 void WorkerProcessLauncher::SetKillProcessTimeoutForTest( |
| 420 const base::TimeDelta& timeout) { |
| 421 core_->SetKillProcessTimeoutForTest(timeout); |
| 422 } |
| 423 |
| 424 |
351 } // namespace remoting | 425 } // namespace remoting |
OLD | NEW |