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 <sddl.h> | |
| 8 #include <limits> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/bind_helpers.h" | |
| 12 #include "base/logging.h" | 7 #include "base/logging.h" |
| 13 #include "base/single_thread_task_runner.h" | 8 #include "base/single_thread_task_runner.h" |
| 14 #include "base/process_util.h" | |
| 15 #include "base/rand_util.h" | |
| 16 #include "base/stringprintf.h" | |
| 17 #include "base/time.h" | 9 #include "base/time.h" |
| 18 #include "base/timer.h" | 10 #include "base/timer.h" |
| 19 #include "base/utf_string_conversions.h" | |
| 20 #include "base/win/object_watcher.h" | 11 #include "base/win/object_watcher.h" |
| 21 #include "base/win/scoped_handle.h" | 12 #include "ipc/ipc_listener.h" |
| 22 #include "ipc/ipc_channel.h" | |
| 23 #include "ipc/ipc_channel_proxy.h" | |
| 24 #include "ipc/ipc_message.h" | 13 #include "ipc/ipc_message.h" |
| 25 #include "net/base/backoff_entry.h" | 14 #include "net/base/backoff_entry.h" |
| 26 #include "remoting/host/host_exit_codes.h" | 15 #include "remoting/host/host_exit_codes.h" |
| 27 #include "remoting/host/worker_process_ipc_delegate.h" | 16 #include "remoting/host/worker_process_ipc_delegate.h" |
| 28 | 17 |
| 18 using base::TimeDelta; | |
| 29 using base::win::ScopedHandle; | 19 using base::win::ScopedHandle; |
| 30 using base::TimeDelta; | |
| 31 | |
| 32 // Match the pipe name prefix used by Chrome IPC channels so that the client | |
| 33 // could use Chrome IPC APIs instead of connecting manually. | |
| 34 const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome."; | |
| 35 | |
| 36 // The minimum and maximum delays between attempts to inject host process into | |
| 37 // a session. | |
| 38 const int kMaxLaunchDelaySeconds = 60; | |
| 39 const int kMinLaunchDelaySeconds = 1; | |
| 40 | 20 |
| 41 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { | 21 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { |
| 42 // Number of initial errors (in sequence) to ignore before applying | 22 // Number of initial errors (in sequence) to ignore before applying |
| 43 // exponential back-off rules. | 23 // exponential back-off rules. |
| 44 0, | 24 0, |
| 45 | 25 |
| 46 // Initial delay for exponential back-off in ms. | 26 // Initial delay for exponential back-off in ms. |
| 47 1000, | 27 1000, |
| 48 | 28 |
| 49 // Factor by which the waiting time will be multiplied. | 29 // Factor by which the waiting time will be multiplied. |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 76 public base::win::ObjectWatcher::Delegate, | 56 public base::win::ObjectWatcher::Delegate, |
| 77 public IPC::Listener { | 57 public IPC::Listener { |
| 78 public: | 58 public: |
| 79 // Creates the launcher that will use |launcher_delegate| to manage the worker | 59 // Creates the launcher that will use |launcher_delegate| to manage the worker |
| 80 // process and |worker_delegate| to handle IPCs. The caller must ensure that | 60 // process and |worker_delegate| to handle IPCs. The caller must ensure that |
| 81 // |worker_delegate| remains valid until Stoppable::Stop() method has been | 61 // |worker_delegate| remains valid until Stoppable::Stop() method has been |
| 82 // called. | 62 // called. |
| 83 // | 63 // |
| 84 // The caller should call all the methods on this class on | 64 // The caller should call all the methods on this class on |
| 85 // the |caller_task_runner| thread. Methods of both delegate interfaces are | 65 // the |caller_task_runner| thread. Methods of both delegate interfaces are |
| 86 // called on the |caller_task_runner| thread as well. |io_task_runner| is used | 66 // called on the |caller_task_runner| thread as well. |
| 87 // to perform background IPC I/O. | |
| 88 Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 67 Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
| 89 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, | |
| 90 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, | 68 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, |
| 91 WorkerProcessIpcDelegate* worker_delegate, | 69 WorkerProcessIpcDelegate* worker_delegate); |
| 92 const std::string& pipe_security_descriptor); | |
| 93 | 70 |
| 94 // Launches the worker process. | 71 // Launches the worker process. |
| 95 void Start(); | 72 void Start(); |
| 96 | 73 |
| 97 // Stops the worker process asynchronously. The caller can drop the reference | 74 // Stops the worker process asynchronously. The caller can drop the reference |
| 98 // to |this| as soon as Stop() returns. | 75 // to |this| as soon as Stop() returns. |
| 99 void Stop(); | 76 void Stop(); |
| 100 | 77 |
| 101 // Sends an IPC message to the worker process. The message will be silently | 78 // Sends an IPC message to the worker process. The message will be silently |
| 102 // dropped if Send() is called before Start() or after stutdown has been | 79 // dropped if Send() is called before Start() or after stutdown has been |
| 103 // initiated. | 80 // initiated. |
| 104 void Send(IPC::Message* message); | 81 void Send(IPC::Message* message); |
| 105 | 82 |
| 106 // base::win::ObjectWatcher::Delegate implementation. | 83 // base::win::ObjectWatcher::Delegate implementation. |
| 107 virtual void OnObjectSignaled(HANDLE object) OVERRIDE; | 84 virtual void OnObjectSignaled(HANDLE object) OVERRIDE; |
| 108 | 85 |
| 109 // IPC::Listener implementation. | 86 // IPC::Listener implementation. |
| 110 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; | 87 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; |
| 111 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; | 88 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; |
| 112 virtual void OnChannelError() OVERRIDE; | 89 virtual void OnChannelError() OVERRIDE; |
| 113 | 90 |
| 114 private: | 91 private: |
| 115 friend class base::RefCountedThreadSafe<Core>; | 92 friend class base::RefCountedThreadSafe<Core>; |
| 116 virtual ~Core(); | 93 virtual ~Core(); |
| 117 | 94 |
| 118 // Creates the server end of the Chromoting IPC channel. | |
| 119 bool CreatePipeForIpcChannel(const std::string& channel_name, | |
| 120 const std::string& pipe_security_descriptor, | |
| 121 base::win::ScopedHandle* pipe_out); | |
| 122 | |
| 123 // Generates random channel ID. | |
| 124 std::string GenerateRandomChannelId(); | |
| 125 | |
| 126 // Attempts to launch the worker process. Schedules next launch attempt if | 95 // Attempts to launch the worker process. Schedules next launch attempt if |
| 127 // creation of the process fails. | 96 // creation of the process fails. |
| 128 void LaunchWorker(); | 97 void LaunchWorker(); |
| 129 | 98 |
| 130 // Records a successfull launch attempt. | 99 // Records a successfull launch attempt. |
| 131 void RecordSuccessfullLaunch(); | 100 void RecordSuccessfullLaunch(); |
| 132 | 101 |
| 133 // Stops the worker process asynchronously and schedules next launch attempt | 102 // Stops the worker process asynchronously and schedules next launch attempt |
| 134 // unless Stop() has been called already. | 103 // unless Stop() has been called already. |
| 135 void StopWorker(); | 104 void StopWorker(); |
| 136 | 105 |
| 137 // All public methods are called on the |caller_task_runner| thread. | 106 // All public methods are called on the |caller_task_runner| thread. |
| 138 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; | 107 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; |
| 139 | 108 |
| 140 // The task runner is used perform background IPC I/O. | |
| 141 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; | |
| 142 | |
| 143 // Implements specifics of launching a worker process. | 109 // Implements specifics of launching a worker process. |
| 144 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate_; | 110 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate_; |
| 145 | 111 |
| 146 // Handles IPC messages sent by the worker process. | 112 // Handles IPC messages sent by the worker process. |
| 147 WorkerProcessIpcDelegate* worker_delegate_; | 113 WorkerProcessIpcDelegate* worker_delegate_; |
| 148 | 114 |
| 149 // The IPC channel connecting to the launched process. | 115 // True if IPC messages should be passed to |worker_delegate_|. |
| 150 scoped_ptr<IPC::ChannelProxy> ipc_channel_; | 116 bool ipc_enabled_; |
| 151 | 117 |
| 152 // The timer used to delay termination of the process in the case of an IPC | 118 // The timer used to delay termination of the process in the case of an IPC |
| 153 // error. | 119 // error. |
| 154 scoped_ptr<base::OneShotTimer<Core> > ipc_error_timer_; | 120 scoped_ptr<base::OneShotTimer<Core> > ipc_error_timer_; |
| 155 | 121 |
| 156 // Launch backoff state. | 122 // Launch backoff state. |
| 157 net::BackoffEntry launch_backoff_; | 123 net::BackoffEntry launch_backoff_; |
| 158 | 124 |
| 159 // Timer used to delay recording a successfull launch. | 125 // Timer used to delay recording a successfull launch. |
| 160 scoped_ptr<base::OneShotTimer<Core> > launch_success_timer_; | 126 scoped_ptr<base::OneShotTimer<Core> > launch_success_timer_; |
| 161 | 127 |
| 162 // Timer used to schedule the next attempt to launch the process. | 128 // Timer used to schedule the next attempt to launch the process. |
| 163 scoped_ptr<base::OneShotTimer<Core> > launch_timer_; | 129 scoped_ptr<base::OneShotTimer<Core> > launch_timer_; |
| 164 | 130 |
| 165 // Used to determine when the launched process terminates. | 131 // Used to determine when the launched process terminates. |
| 166 base::win::ObjectWatcher process_watcher_; | 132 base::win::ObjectWatcher process_watcher_; |
| 167 | 133 |
| 168 // A waiting handle that becomes signalled once the launched process has | 134 // A waiting handle that becomes signalled once the launched process has |
| 169 // been terminated. | 135 // been terminated. |
| 170 base::win::ScopedHandle process_exit_event_; | 136 ScopedHandle process_exit_event_; |
| 171 | |
| 172 // The server end of the pipe. | |
| 173 base::win::ScopedHandle pipe_; | |
| 174 | |
| 175 // The security descriptor (as SDDL) of the server end of the pipe. | |
| 176 std::string pipe_security_descriptor_; | |
| 177 | 137 |
| 178 // Self reference to keep the object alive while the worker process is being | 138 // Self reference to keep the object alive while the worker process is being |
| 179 // terminated. | 139 // terminated. |
| 180 scoped_refptr<Core> self_; | 140 scoped_refptr<Core> self_; |
| 181 | 141 |
| 182 // True when Stop() has been called. | 142 // True when Stop() has been called. |
| 183 bool stopping_; | 143 bool stopping_; |
| 184 | 144 |
| 185 DISALLOW_COPY_AND_ASSIGN(Core); | 145 DISALLOW_COPY_AND_ASSIGN(Core); |
| 186 }; | 146 }; |
| 187 | 147 |
| 188 WorkerProcessLauncher::Delegate::~Delegate() { | 148 WorkerProcessLauncher::Delegate::~Delegate() { |
| 189 } | 149 } |
| 190 | 150 |
| 191 WorkerProcessLauncher::Core::Core( | 151 WorkerProcessLauncher::Core::Core( |
| 192 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 152 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
| 193 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, | |
| 194 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, | 153 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, |
| 195 WorkerProcessIpcDelegate* worker_delegate, | 154 WorkerProcessIpcDelegate* worker_delegate) |
| 196 const std::string& pipe_security_descriptor) | |
| 197 : caller_task_runner_(caller_task_runner), | 155 : caller_task_runner_(caller_task_runner), |
| 198 io_task_runner_(io_task_runner), | |
| 199 launcher_delegate_(launcher_delegate.Pass()), | 156 launcher_delegate_(launcher_delegate.Pass()), |
| 200 worker_delegate_(worker_delegate), | 157 worker_delegate_(worker_delegate), |
| 158 ipc_enabled_(false), | |
| 201 launch_backoff_(&kDefaultBackoffPolicy), | 159 launch_backoff_(&kDefaultBackoffPolicy), |
| 202 pipe_security_descriptor_(pipe_security_descriptor), | |
| 203 stopping_(false) { | 160 stopping_(false) { |
| 204 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 161 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 205 | 162 |
| 206 // base::OneShotTimer must be destroyed on the same thread it was created on. | 163 // base::OneShotTimer must be destroyed on the same thread it was created on. |
| 207 ipc_error_timer_.reset(new base::OneShotTimer<Core>()); | 164 ipc_error_timer_.reset(new base::OneShotTimer<Core>()); |
| 208 launch_success_timer_.reset(new base::OneShotTimer<Core>()); | 165 launch_success_timer_.reset(new base::OneShotTimer<Core>()); |
| 209 launch_timer_.reset(new base::OneShotTimer<Core>()); | 166 launch_timer_.reset(new base::OneShotTimer<Core>()); |
| 210 } | 167 } |
| 211 | 168 |
| 212 void WorkerProcessLauncher::Core::Start() { | 169 void WorkerProcessLauncher::Core::Start() { |
| 213 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 170 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 214 DCHECK(!stopping_); | 171 DCHECK(!stopping_); |
| 215 | 172 |
| 216 LaunchWorker(); | 173 LaunchWorker(); |
| 217 } | 174 } |
| 218 | 175 |
| 219 void WorkerProcessLauncher::Core::Stop() { | 176 void WorkerProcessLauncher::Core::Stop() { |
| 220 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 177 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 221 | 178 |
| 222 if (!stopping_) { | 179 if (!stopping_) { |
| 223 stopping_ = true; | 180 stopping_ = true; |
| 224 worker_delegate_ = NULL; | 181 worker_delegate_ = NULL; |
| 225 StopWorker(); | 182 StopWorker(); |
| 226 } | 183 } |
| 227 } | 184 } |
| 228 | 185 |
| 229 void WorkerProcessLauncher::Core::Send(IPC::Message* message) { | 186 void WorkerProcessLauncher::Core::Send(IPC::Message* message) { |
| 230 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 187 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 231 | 188 |
| 232 if (ipc_channel_.get()) { | 189 launcher_delegate_->Send(message); |
| 233 ipc_channel_->Send(message); | |
| 234 } else { | |
| 235 delete message; | |
| 236 } | |
| 237 } | 190 } |
| 238 | 191 |
| 239 void WorkerProcessLauncher::Core::OnObjectSignaled(HANDLE object) { | 192 void WorkerProcessLauncher::Core::OnObjectSignaled(HANDLE object) { |
| 240 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 193 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 241 DCHECK(process_watcher_.GetWatchedObject() == NULL); | 194 DCHECK(process_watcher_.GetWatchedObject() == NULL); |
| 242 | 195 |
| 243 StopWorker(); | 196 StopWorker(); |
| 244 } | 197 } |
| 245 | 198 |
| 246 bool WorkerProcessLauncher::Core::OnMessageReceived( | 199 bool WorkerProcessLauncher::Core::OnMessageReceived( |
| 247 const IPC::Message& message) { | 200 const IPC::Message& message) { |
| 248 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 201 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 249 DCHECK(ipc_channel_.get() != NULL); | 202 |
| 203 if (!ipc_enabled_) | |
| 204 return false; | |
| 250 | 205 |
| 251 return worker_delegate_->OnMessageReceived(message); | 206 return worker_delegate_->OnMessageReceived(message); |
| 252 } | 207 } |
| 253 | 208 |
| 254 void WorkerProcessLauncher::Core::OnChannelConnected(int32 peer_pid) { | 209 void WorkerProcessLauncher::Core::OnChannelConnected(int32 peer_pid) { |
| 255 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 210 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 256 DCHECK(ipc_channel_.get() != NULL); | |
| 257 | 211 |
| 258 // |peer_pid| is send by the client and cannot be trusted. | 212 // |peer_pid| is send by the client and cannot be trusted. |
| 259 // GetNamedPipeClientProcessId() is not available on XP. The pipe's security | 213 // GetNamedPipeClientProcessId() is not available on XP. The pipe's security |
| 260 // descriptor is the only protection we currently have against malicious | 214 // descriptor is the only protection we currently have against malicious |
| 261 // clients. | 215 // clients. |
| 262 // | 216 // |
| 263 // If we'd like to be able to launch low-privileged workers and let them | 217 // If we'd like to be able to launch low-privileged workers and let them |
| 264 // connect back, the pipe handle should be passed to the worker instead of | 218 // connect back, the pipe handle should be passed to the worker instead of |
| 265 // the pipe name. | 219 // the pipe name. |
| 266 worker_delegate_->OnChannelConnected(); | 220 if (ipc_enabled_) |
| 221 worker_delegate_->OnChannelConnected(); | |
| 267 } | 222 } |
| 268 | 223 |
| 269 void WorkerProcessLauncher::Core::OnChannelError() { | 224 void WorkerProcessLauncher::Core::OnChannelError() { |
| 270 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 225 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 271 DCHECK(ipc_channel_.get() != NULL); | |
| 272 | 226 |
| 273 // Schedule a delayed termination of the worker process. Usually, the pipe is | 227 // Schedule a delayed termination of the worker process. Usually, the pipe is |
| 274 // disconnected when the worker process is about to exit. Waiting a little bit | 228 // disconnected when the worker process is about to exit. Waiting a little bit |
| 275 // here allows the worker to exit completely and so, notify | 229 // here allows the worker to exit completely and so, notify |
| 276 // |process_watcher_|. As the result KillProcess() will not be called and | 230 // |process_watcher_|. As the result KillProcess() will not be called and |
| 277 // the original exit code reported by the worker process will be retrieved. | 231 // the original exit code reported by the worker process will be retrieved. |
| 278 ipc_error_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(5), | 232 ipc_error_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(5), |
| 279 this, &Core::StopWorker); | 233 this, &Core::StopWorker); |
| 280 } | 234 } |
| 281 | 235 |
| 282 WorkerProcessLauncher::Core::~Core() { | 236 WorkerProcessLauncher::Core::~Core() { |
| 283 DCHECK(stopping_); | 237 DCHECK(stopping_); |
| 284 } | 238 } |
| 285 | 239 |
| 286 // Creates the server end of the Chromoting IPC channel. | |
| 287 bool WorkerProcessLauncher::Core::CreatePipeForIpcChannel( | |
| 288 const std::string& channel_name, | |
| 289 const std::string& pipe_security_descriptor, | |
| 290 ScopedHandle* pipe_out) { | |
| 291 // Create security descriptor for the channel. | |
| 292 SECURITY_ATTRIBUTES security_attributes; | |
| 293 security_attributes.nLength = sizeof(security_attributes); | |
| 294 security_attributes.bInheritHandle = FALSE; | |
| 295 | |
| 296 ULONG security_descriptor_length = 0; | |
| 297 if (!ConvertStringSecurityDescriptorToSecurityDescriptor( | |
| 298 UTF8ToUTF16(pipe_security_descriptor).c_str(), | |
| 299 SDDL_REVISION_1, | |
| 300 reinterpret_cast<PSECURITY_DESCRIPTOR*>( | |
| 301 &security_attributes.lpSecurityDescriptor), | |
| 302 &security_descriptor_length)) { | |
| 303 LOG_GETLASTERROR(ERROR) << | |
| 304 "Failed to create a security descriptor for the Chromoting IPC channel"; | |
| 305 return false; | |
| 306 } | |
| 307 | |
| 308 // Convert the channel name to the pipe name. | |
| 309 std::string pipe_name(kChromePipeNamePrefix); | |
| 310 pipe_name.append(channel_name); | |
| 311 | |
| 312 // Create the server end of the pipe. This code should match the code in | |
| 313 // IPC::Channel with exception of passing a non-default security descriptor. | |
| 314 base::win::ScopedHandle pipe; | |
| 315 pipe.Set(CreateNamedPipe( | |
| 316 UTF8ToUTF16(pipe_name).c_str(), | |
| 317 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, | |
| 318 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, | |
| 319 1, | |
| 320 IPC::Channel::kReadBufferSize, | |
| 321 IPC::Channel::kReadBufferSize, | |
| 322 5000, | |
| 323 &security_attributes)); | |
| 324 if (!pipe.IsValid()) { | |
| 325 LOG_GETLASTERROR(ERROR) << | |
| 326 "Failed to create the server end of the Chromoting IPC channel"; | |
| 327 LocalFree(security_attributes.lpSecurityDescriptor); | |
| 328 return false; | |
| 329 } | |
| 330 | |
| 331 LocalFree(security_attributes.lpSecurityDescriptor); | |
| 332 | |
| 333 *pipe_out = pipe.Pass(); | |
| 334 return true; | |
| 335 } | |
| 336 | |
| 337 // N.B. Copied from src/content/common/child_process_host_impl.cc | |
| 338 std::string WorkerProcessLauncher::Core::GenerateRandomChannelId() { | |
| 339 return base::StringPrintf("%d.%p.%d", | |
| 340 base::GetCurrentProcId(), this, | |
| 341 base::RandInt(0, std::numeric_limits<int>::max())); | |
| 342 } | |
| 343 | |
| 344 void WorkerProcessLauncher::Core::LaunchWorker() { | 240 void WorkerProcessLauncher::Core::LaunchWorker() { |
| 345 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 241 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 346 DCHECK(ipc_channel_.get() == NULL); | 242 DCHECK(!ipc_enabled_); |
| 347 DCHECK(!launch_success_timer_->IsRunning()); | 243 DCHECK(!launch_success_timer_->IsRunning()); |
| 348 DCHECK(!launch_timer_->IsRunning()); | 244 DCHECK(!launch_timer_->IsRunning()); |
| 349 DCHECK(!pipe_.IsValid()); | |
| 350 DCHECK(!process_exit_event_.IsValid()); | 245 DCHECK(!process_exit_event_.IsValid()); |
| 351 DCHECK(process_watcher_.GetWatchedObject() == NULL); | 246 DCHECK(process_watcher_.GetWatchedObject() == NULL); |
| 352 | 247 |
| 353 std::string channel_name = GenerateRandomChannelId(); | 248 // Launch the process and attach an object watcher to the returned process |
| 354 if (CreatePipeForIpcChannel(channel_name, pipe_security_descriptor_, | 249 // handle so that we get notified if the process terminates. |
| 355 &pipe_)) { | 250 if (launcher_delegate_->LaunchProcess(this, &process_exit_event_)) { |
| 356 // Wrap the pipe into an IPC channel. | 251 if (process_watcher_.StartWatching(process_exit_event_, this)) { |
| 357 ipc_channel_.reset(new IPC::ChannelProxy( | 252 ipc_enabled_ = true; |
| 358 IPC::ChannelHandle(pipe_), | 253 // Record a successful launch once the process has been running for at |
| 359 IPC::Channel::MODE_SERVER, | 254 // least two seconds. |
| 360 this, | 255 launch_success_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(2), |
| 361 io_task_runner_)); | 256 this, &Core::RecordSuccessfullLaunch); |
|
simonmorris
2012/10/12 16:31:13
Successfull -> Successful
alexeypa (please no reviews)
2012/10/12 18:44:39
Done.
| |
| 257 return; | |
| 258 } | |
| 362 | 259 |
| 363 // Launch the process and attach an object watcher to the returned process | 260 launcher_delegate_->KillProcess(CONTROL_C_EXIT); |
| 364 // handle so that we get notified if the process terminates. | |
| 365 if (launcher_delegate_->LaunchProcess(channel_name, &process_exit_event_)) { | |
| 366 if (process_watcher_.StartWatching(process_exit_event_, this)) { | |
| 367 // Record a successful launch once the process has been running for at | |
| 368 // least two seconds. | |
| 369 launch_success_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(2), | |
| 370 this, &Core::RecordSuccessfullLaunch); | |
| 371 return; | |
| 372 } | |
| 373 | |
| 374 launcher_delegate_->KillProcess(CONTROL_C_EXIT); | |
| 375 } | |
| 376 } | 261 } |
| 377 | 262 |
| 378 launch_backoff_.InformOfRequest(false); | 263 launch_backoff_.InformOfRequest(false); |
| 379 StopWorker(); | 264 StopWorker(); |
| 380 } | 265 } |
| 381 | 266 |
| 382 void WorkerProcessLauncher::Core::RecordSuccessfullLaunch() { | 267 void WorkerProcessLauncher::Core::RecordSuccessfullLaunch() { |
| 383 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 268 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 384 | 269 |
| 385 launch_backoff_.InformOfRequest(true); | 270 launch_backoff_.InformOfRequest(true); |
| 386 } | 271 } |
| 387 | 272 |
| 388 void WorkerProcessLauncher::Core::StopWorker() { | 273 void WorkerProcessLauncher::Core::StopWorker() { |
| 389 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 274 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 390 | 275 |
| 391 // Record a launch failure if the process exited too soon. | 276 // Record a launch failure if the process exited too soon. |
| 392 if (launch_success_timer_->IsRunning()) { | 277 if (launch_success_timer_->IsRunning()) { |
| 393 launch_success_timer_->Stop(); | 278 launch_success_timer_->Stop(); |
| 394 launch_backoff_.InformOfRequest(false); | 279 launch_backoff_.InformOfRequest(false); |
| 395 } | 280 } |
| 396 | 281 |
| 397 // Keep |this| alive until the worker process is terminated. | 282 // Keep |this| alive until the worker process is terminated. |
| 398 self_ = this; | 283 self_ = this; |
| 399 | 284 |
| 400 ipc_channel_.reset(); | 285 // Ignore any remaining IPC messages. |
| 401 pipe_.Close(); | 286 ipc_enabled_ = false; |
| 402 | 287 |
| 403 // Kill the process if it has been started already. | 288 // Kill the process if it has been started already. |
| 404 if (process_watcher_.GetWatchedObject() != NULL) { | 289 if (process_watcher_.GetWatchedObject() != NULL) { |
| 405 launcher_delegate_->KillProcess(CONTROL_C_EXIT); | 290 launcher_delegate_->KillProcess(CONTROL_C_EXIT); |
| 406 return; | 291 return; |
| 407 } | 292 } |
| 408 | 293 |
| 409 ipc_error_timer_->Stop(); | |
| 410 | |
| 411 DCHECK(ipc_channel_.get() == NULL); | |
| 412 DCHECK(!pipe_.IsValid()); | |
| 413 DCHECK(process_watcher_.GetWatchedObject() == NULL); | 294 DCHECK(process_watcher_.GetWatchedObject() == NULL); |
| 414 | 295 |
| 296 ipc_error_timer_->Stop(); | |
| 415 process_exit_event_.Close(); | 297 process_exit_event_.Close(); |
| 416 | 298 |
| 417 // Do not relaunch the worker process if the caller has asked us to stop. | 299 // Do not relaunch the worker process if the caller has asked us to stop. |
| 418 if (stopping_) { | 300 if (stopping_) { |
| 419 ipc_error_timer_.reset(); | 301 ipc_error_timer_.reset(); |
| 420 launch_timer_.reset(); | 302 launch_timer_.reset(); |
| 421 self_ = NULL; | 303 self_ = NULL; |
| 422 return; | 304 return; |
| 423 } | 305 } |
| 424 | 306 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 436 return; | 318 return; |
| 437 } | 319 } |
| 438 | 320 |
| 439 // Schedule the next attempt to launch the worker process. | 321 // Schedule the next attempt to launch the worker process. |
| 440 launch_timer_->Start(FROM_HERE, launch_backoff_.GetTimeUntilRelease(), | 322 launch_timer_->Start(FROM_HERE, launch_backoff_.GetTimeUntilRelease(), |
| 441 this, &Core::LaunchWorker); | 323 this, &Core::LaunchWorker); |
| 442 } | 324 } |
| 443 | 325 |
| 444 WorkerProcessLauncher::WorkerProcessLauncher( | 326 WorkerProcessLauncher::WorkerProcessLauncher( |
| 445 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 327 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
| 446 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, | |
| 447 scoped_ptr<Delegate> launcher_delegate, | 328 scoped_ptr<Delegate> launcher_delegate, |
| 448 WorkerProcessIpcDelegate* worker_delegate, | 329 WorkerProcessIpcDelegate* worker_delegate) { |
| 449 const std::string& pipe_security_descriptor) { | 330 core_ = new Core(caller_task_runner, launcher_delegate.Pass(), |
| 450 core_ = new Core(caller_task_runner, io_task_runner, launcher_delegate.Pass(), | 331 worker_delegate); |
| 451 worker_delegate, pipe_security_descriptor); | |
| 452 core_->Start(); | 332 core_->Start(); |
| 453 } | 333 } |
| 454 | 334 |
| 455 WorkerProcessLauncher::~WorkerProcessLauncher() { | 335 WorkerProcessLauncher::~WorkerProcessLauncher() { |
| 456 core_->Stop(); | 336 core_->Stop(); |
| 457 core_ = NULL; | 337 core_ = NULL; |
| 458 } | 338 } |
| 459 | 339 |
| 460 void WorkerProcessLauncher::Send(IPC::Message* message) { | 340 void WorkerProcessLauncher::Send(IPC::Message* message) { |
| 461 core_->Send(message); | 341 core_->Send(message); |
| 462 } | 342 } |
| 463 | 343 |
| 464 } // namespace remoting | 344 } // namespace remoting |
| OLD | NEW |