Chromium Code Reviews| 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 |