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 |