 Chromium Code Reviews
 Chromium Code Reviews Issue 12545006:
  The worker process launcher can now ask the worker to crash.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 12545006:
  The worker process launcher can now ask the worker to crash.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| 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 |