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 "content/browser/child_process_launcher.h" | 5 #include "content/browser/child_process_launcher.h" |
6 | 6 |
7 #include <utility> // For std::pair. | 7 #include <utility> // For std::pair. |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 14 matching lines...) Expand all Loading... | |
25 #include "base/files/file_path.h" | 25 #include "base/files/file_path.h" |
26 #include "content/common/sandbox_win.h" | 26 #include "content/common/sandbox_win.h" |
27 #include "content/public/common/sandbox_init.h" | 27 #include "content/public/common/sandbox_init.h" |
28 #include "content/public/common/sandboxed_process_launcher_delegate.h" | 28 #include "content/public/common/sandboxed_process_launcher_delegate.h" |
29 #elif defined(OS_MACOSX) | 29 #elif defined(OS_MACOSX) |
30 #include "content/browser/mach_broker_mac.h" | 30 #include "content/browser/mach_broker_mac.h" |
31 #elif defined(OS_ANDROID) | 31 #elif defined(OS_ANDROID) |
32 #include "base/android/jni_android.h" | 32 #include "base/android/jni_android.h" |
33 #include "content/browser/android/child_process_launcher_android.h" | 33 #include "content/browser/android/child_process_launcher_android.h" |
34 #elif defined(OS_POSIX) | 34 #elif defined(OS_POSIX) |
35 #include "base/memory/shared_memory.h" | |
35 #include "base/memory/singleton.h" | 36 #include "base/memory/singleton.h" |
36 #include "content/browser/renderer_host/render_sandbox_host_linux.h" | 37 #include "content/browser/renderer_host/render_sandbox_host_linux.h" |
37 #include "content/browser/zygote_host/zygote_host_impl_linux.h" | 38 #include "content/browser/zygote_host/zygote_host_impl_linux.h" |
38 #include "content/common/child_process_sandbox_support_impl_linux.h" | 39 #include "content/common/child_process_sandbox_support_impl_linux.h" |
39 #endif | 40 #endif |
40 | 41 |
41 #if defined(OS_POSIX) | 42 #if defined(OS_POSIX) |
43 #include "base/metrics/stats_table.h" | |
42 #include "base/posix/global_descriptors.h" | 44 #include "base/posix/global_descriptors.h" |
43 #endif | 45 #endif |
44 | 46 |
45 namespace content { | 47 namespace content { |
46 | 48 |
47 // Having the functionality of ChildProcessLauncher be in an internal | 49 // Having the functionality of ChildProcessLauncher be in an internal |
48 // ref counted object allows us to automatically terminate the process when the | 50 // ref counted object allows us to automatically terminate the process when the |
49 // parent class destructs, while still holding on to state that we need. | 51 // parent class destructs, while still holding on to state that we need. |
50 class ChildProcessLauncher::Context | 52 class ChildProcessLauncher::Context |
51 : public base::RefCountedThreadSafe<ChildProcessLauncher::Context> { | 53 : public base::RefCountedThreadSafe<ChildProcessLauncher::Context> { |
(...skipping 12 matching lines...) Expand all Loading... | |
64 terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()-> | 66 terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()-> |
65 HasSwitch(switches::kChildCleanExit); | 67 HasSwitch(switches::kChildCleanExit); |
66 #else | 68 #else |
67 terminate_child_on_shutdown_ = true; | 69 terminate_child_on_shutdown_ = true; |
68 #endif | 70 #endif |
69 } | 71 } |
70 | 72 |
71 void Launch( | 73 void Launch( |
72 #if defined(OS_WIN) | 74 #if defined(OS_WIN) |
73 SandboxedProcessLauncherDelegate* delegate, | 75 SandboxedProcessLauncherDelegate* delegate, |
76 bool launch_elevated, | |
74 #elif defined(OS_ANDROID) | 77 #elif defined(OS_ANDROID) |
75 int ipcfd, | 78 int ipcfd, |
76 #elif defined(OS_POSIX) | 79 #elif defined(OS_POSIX) |
77 bool use_zygote, | 80 bool use_zygote, |
78 const base::EnvironmentMap& environ, | 81 const base::EnvironmentMap& environ, |
79 int ipcfd, | 82 int ipcfd, |
80 #endif | 83 #endif |
81 CommandLine* cmd_line, | 84 CommandLine* cmd_line, |
82 int child_process_id, | 85 int child_process_id, |
83 Client* client) { | 86 Client* client) { |
84 client_ = client; | 87 client_ = client; |
85 | 88 |
86 CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_)); | 89 CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_)); |
87 | 90 |
88 #if defined(OS_ANDROID) | 91 #if defined(OS_ANDROID) |
89 // We need to close the client end of the IPC channel to reliably detect | 92 // We need to close the client end of the IPC channel to reliably detect |
90 // child termination. We will close this fd after we create the child | 93 // child termination. We will close this fd after we create the child |
91 // process which is asynchronous on Android. | 94 // process which is asynchronous on Android. |
92 ipcfd_ = ipcfd; | 95 ipcfd_ = ipcfd; |
93 #endif | 96 #endif |
94 BrowserThread::PostTask( | 97 BrowserThread::PostTask( |
95 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, | 98 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, |
96 base::Bind( | 99 base::Bind( |
97 &Context::LaunchInternal, | 100 &Context::LaunchInternal, |
98 make_scoped_refptr(this), | 101 make_scoped_refptr(this), |
99 client_thread_id_, | 102 client_thread_id_, |
100 child_process_id, | 103 child_process_id, |
101 #if defined(OS_WIN) | 104 #if defined(OS_WIN) |
102 delegate, | 105 delegate, |
106 launch_elevated, | |
103 #elif defined(OS_ANDROID) | 107 #elif defined(OS_ANDROID) |
104 ipcfd, | 108 ipcfd, |
105 #elif defined(OS_POSIX) | 109 #elif defined(OS_POSIX) |
106 use_zygote, | 110 use_zygote, |
107 environ, | 111 environ, |
108 ipcfd, | 112 ipcfd, |
109 #endif | 113 #endif |
114 | |
jam
2014/01/30 21:41:03
nit: drop the empty line
Drew Haven
2014/01/31 20:00:12
Done.
| |
110 cmd_line)); | 115 cmd_line)); |
111 } | 116 } |
112 | 117 |
113 #if defined(OS_ANDROID) | 118 #if defined(OS_ANDROID) |
114 static void OnChildProcessStarted( | 119 static void OnChildProcessStarted( |
115 // |this_object| is NOT thread safe. Only use it to post a task back. | 120 // |this_object| is NOT thread safe. Only use it to post a task back. |
116 scoped_refptr<Context> this_object, | 121 scoped_refptr<Context> this_object, |
117 BrowserThread::ID client_thread_id, | 122 BrowserThread::ID client_thread_id, |
118 const base::TimeTicks begin_launch_time, | 123 const base::TimeTicks begin_launch_time, |
119 base::ProcessHandle handle) { | 124 base::ProcessHandle handle) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 } | 181 } |
177 } | 182 } |
178 | 183 |
179 static void LaunchInternal( | 184 static void LaunchInternal( |
180 // |this_object| is NOT thread safe. Only use it to post a task back. | 185 // |this_object| is NOT thread safe. Only use it to post a task back. |
181 scoped_refptr<Context> this_object, | 186 scoped_refptr<Context> this_object, |
182 BrowserThread::ID client_thread_id, | 187 BrowserThread::ID client_thread_id, |
183 int child_process_id, | 188 int child_process_id, |
184 #if defined(OS_WIN) | 189 #if defined(OS_WIN) |
185 SandboxedProcessLauncherDelegate* delegate, | 190 SandboxedProcessLauncherDelegate* delegate, |
191 bool launch_elevated, | |
186 #elif defined(OS_ANDROID) | 192 #elif defined(OS_ANDROID) |
187 int ipcfd, | 193 int ipcfd, |
188 #elif defined(OS_POSIX) | 194 #elif defined(OS_POSIX) |
189 bool use_zygote, | 195 bool use_zygote, |
190 const base::EnvironmentMap& env, | 196 const base::EnvironmentMap& env, |
191 int ipcfd, | 197 int ipcfd, |
192 #endif | 198 #endif |
193 CommandLine* cmd_line) { | 199 CommandLine* cmd_line) { |
194 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line); | 200 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line); |
195 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); | 201 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); |
196 | 202 |
197 #if defined(OS_WIN) | 203 #if defined(OS_WIN) |
198 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); | 204 base::ProcessHandle handle = base::kNullProcessHandle; |
199 base::ProcessHandle handle = StartSandboxedProcess(delegate, cmd_line); | 205 if (launch_elevated) { |
200 #elif defined(OS_ANDROID) | 206 base::LaunchOptions options; |
201 // Android WebView runs in single process, ensure that we never get here | 207 options.start_hidden = true; |
202 // when running in single process mode. | 208 base::LaunchElevatedProcess(*cmd_line, options, &handle); |
203 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); | 209 } else { |
204 | 210 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); |
211 handle = StartSandboxedProcess(delegate, cmd_line); | |
212 } | |
213 #elif defined(OS_POSIX) | |
205 std::string process_type = | 214 std::string process_type = |
206 cmd_line->GetSwitchValueASCII(switches::kProcessType); | 215 cmd_line->GetSwitchValueASCII(switches::kProcessType); |
207 std::vector<FileDescriptorInfo> files_to_register; | 216 std::vector<FileDescriptorInfo> files_to_register; |
208 files_to_register.push_back( | 217 files_to_register.push_back( |
209 FileDescriptorInfo(kPrimaryIPCChannel, | 218 FileDescriptorInfo(kPrimaryIPCChannel, |
210 base::FileDescriptor(ipcfd, false))); | 219 base::FileDescriptor(ipcfd, false))); |
220 base::StatsTable* stats_table = base::StatsTable::current(); | |
jam
2014/01/30 21:41:03
this, and some of the other changes in this file a
Drew Haven
2014/01/31 20:00:12
Done.
| |
221 if (stats_table && | |
222 base::SharedMemory::IsHandleValid( | |
223 stats_table->GetSharedMemoryHandle())) { | |
224 files_to_register.push_back( | |
225 FileDescriptorInfo(kStatsTableSharedMemFd, | |
226 stats_table->GetSharedMemoryHandle())); | |
227 } | |
228 #endif | |
229 | |
230 #if defined(OS_ANDROID) | |
231 // Android WebView runs in single process, ensure that we never get here | |
232 // when running in single process mode. | |
233 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); | |
211 | 234 |
212 GetContentClient()->browser()-> | 235 GetContentClient()->browser()-> |
213 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, | 236 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, |
214 &files_to_register); | 237 &files_to_register); |
215 | 238 |
216 StartChildProcess(cmd_line->argv(), files_to_register, | 239 StartChildProcess(cmd_line->argv(), files_to_register, |
217 base::Bind(&ChildProcessLauncher::Context::OnChildProcessStarted, | 240 base::Bind(&ChildProcessLauncher::Context::OnChildProcessStarted, |
218 this_object, client_thread_id, begin_launch_time)); | 241 this_object, client_thread_id, begin_launch_time)); |
219 | 242 |
220 #elif defined(OS_POSIX) | 243 #elif defined(OS_POSIX) |
221 base::ProcessHandle handle = base::kNullProcessHandle; | 244 base::ProcessHandle handle = base::kNullProcessHandle; |
222 // We need to close the client end of the IPC channel to reliably detect | 245 // We need to close the client end of the IPC channel to reliably detect |
223 // child termination. | 246 // child termination. |
224 file_util::ScopedFD ipcfd_closer(&ipcfd); | 247 file_util::ScopedFD ipcfd_closer(&ipcfd); |
225 | 248 |
226 std::string process_type = | |
227 cmd_line->GetSwitchValueASCII(switches::kProcessType); | |
228 std::vector<FileDescriptorInfo> files_to_register; | |
229 files_to_register.push_back( | |
230 FileDescriptorInfo(kPrimaryIPCChannel, | |
231 base::FileDescriptor(ipcfd, false))); | |
232 | |
233 #if !defined(OS_MACOSX) | 249 #if !defined(OS_MACOSX) |
234 GetContentClient()->browser()-> | 250 GetContentClient()->browser()-> |
235 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, | 251 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, |
236 &files_to_register); | 252 &files_to_register); |
237 if (use_zygote) { | 253 if (use_zygote) { |
238 handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(), | 254 handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(), |
239 files_to_register, | 255 files_to_register, |
240 process_type); | 256 process_type); |
241 } else | 257 } else |
242 // Fall through to the normal posix case below when we're not zygoting. | 258 // Fall through to the normal posix case below when we're not zygoting. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 #endif | 339 #endif |
324 starting_ = false; | 340 starting_ = false; |
325 process_.set_handle(handle); | 341 process_.set_handle(handle); |
326 if (!handle) | 342 if (!handle) |
327 LOG(ERROR) << "Failed to launch child process"; | 343 LOG(ERROR) << "Failed to launch child process"; |
328 | 344 |
329 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) | 345 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
330 zygote_ = zygote; | 346 zygote_ = zygote; |
331 #endif | 347 #endif |
332 if (client_) { | 348 if (client_) { |
333 client_->OnProcessLaunched(); | 349 if (handle) { |
350 client_->OnProcessLaunched(); | |
351 } else { | |
352 client_->OnProcessLaunchFailed(); | |
353 } | |
334 } else { | 354 } else { |
335 Terminate(); | 355 Terminate(); |
336 } | 356 } |
337 } | 357 } |
338 | 358 |
339 void Terminate() { | 359 void Terminate() { |
340 if (!process_.handle()) | 360 if (!process_.handle()) |
341 return; | 361 return; |
342 | 362 |
343 if (!terminate_child_on_shutdown_) | 363 if (!terminate_child_on_shutdown_) |
(...skipping 17 matching lines...) Expand all Loading... | |
361 base::Process process(handle); | 381 base::Process process(handle); |
362 process.SetProcessBackgrounded(background); | 382 process.SetProcessBackgrounded(background); |
363 } | 383 } |
364 | 384 |
365 static void TerminateInternal( | 385 static void TerminateInternal( |
366 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) | 386 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
367 bool zygote, | 387 bool zygote, |
368 #endif | 388 #endif |
369 base::ProcessHandle handle) { | 389 base::ProcessHandle handle) { |
370 #if defined(OS_ANDROID) | 390 #if defined(OS_ANDROID) |
371 LOG(INFO) << "ChromeProcess: Stopping process with handle " << handle; | 391 VLOG(0) << "ChromeProcess: Stopping process with handle " << handle; |
372 StopChildProcess(handle); | 392 StopChildProcess(handle); |
373 #else | 393 #else |
374 base::Process process(handle); | 394 base::Process process(handle); |
375 // Client has gone away, so just kill the process. Using exit code 0 | 395 // Client has gone away, so just kill the process. Using exit code 0 |
376 // means that UMA won't treat this as a crash. | 396 // means that UMA won't treat this as a crash. |
377 process.Terminate(RESULT_CODE_NORMAL_EXIT); | 397 process.Terminate(RESULT_CODE_NORMAL_EXIT); |
378 // On POSIX, we must additionally reap the child. | 398 // On POSIX, we must additionally reap the child. |
379 #if defined(OS_POSIX) | 399 #if defined(OS_POSIX) |
380 #if !defined(OS_MACOSX) | 400 #if !defined(OS_MACOSX) |
381 if (zygote) { | 401 if (zygote) { |
(...skipping 24 matching lines...) Expand all Loading... | |
406 int ipcfd_; | 426 int ipcfd_; |
407 #elif defined(OS_POSIX) && !defined(OS_MACOSX) | 427 #elif defined(OS_POSIX) && !defined(OS_MACOSX) |
408 bool zygote_; | 428 bool zygote_; |
409 #endif | 429 #endif |
410 }; | 430 }; |
411 | 431 |
412 | 432 |
413 ChildProcessLauncher::ChildProcessLauncher( | 433 ChildProcessLauncher::ChildProcessLauncher( |
414 #if defined(OS_WIN) | 434 #if defined(OS_WIN) |
415 SandboxedProcessLauncherDelegate* delegate, | 435 SandboxedProcessLauncherDelegate* delegate, |
436 bool launch_elevated, | |
416 #elif defined(OS_POSIX) | 437 #elif defined(OS_POSIX) |
417 bool use_zygote, | 438 bool use_zygote, |
418 const base::EnvironmentMap& environ, | 439 const base::EnvironmentMap& environ, |
419 int ipcfd, | 440 int ipcfd, |
420 #endif | 441 #endif |
421 CommandLine* cmd_line, | 442 CommandLine* cmd_line, |
422 int child_process_id, | 443 int child_process_id, |
423 Client* client) { | 444 Client* client) { |
424 context_ = new Context(); | 445 context_ = new Context(); |
425 context_->Launch( | 446 context_->Launch( |
426 #if defined(OS_WIN) | 447 #if defined(OS_WIN) |
427 delegate, | 448 delegate, |
449 launch_elevated, | |
428 #elif defined(OS_ANDROID) | 450 #elif defined(OS_ANDROID) |
429 ipcfd, | 451 ipcfd, |
430 #elif defined(OS_POSIX) | 452 #elif defined(OS_POSIX) |
431 use_zygote, | 453 use_zygote, |
432 environ, | 454 environ, |
433 ipcfd, | 455 ipcfd, |
434 #endif | 456 #endif |
435 cmd_line, | 457 cmd_line, |
436 child_process_id, | 458 child_process_id, |
437 client); | 459 client); |
(...skipping 19 matching lines...) Expand all Loading... | |
457 if (handle == base::kNullProcessHandle) { | 479 if (handle == base::kNullProcessHandle) { |
458 // Process is already gone, so return the cached termination status. | 480 // Process is already gone, so return the cached termination status. |
459 if (exit_code) | 481 if (exit_code) |
460 *exit_code = context_->exit_code_; | 482 *exit_code = context_->exit_code_; |
461 return context_->termination_status_; | 483 return context_->termination_status_; |
462 } | 484 } |
463 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) | 485 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
464 if (context_->zygote_) { | 486 if (context_->zygote_) { |
465 context_->termination_status_ = ZygoteHostImpl::GetInstance()-> | 487 context_->termination_status_ = ZygoteHostImpl::GetInstance()-> |
466 GetTerminationStatus(handle, known_dead, &context_->exit_code_); | 488 GetTerminationStatus(handle, known_dead, &context_->exit_code_); |
467 } else | 489 } else if (known_dead) { |
490 context_->termination_status_ = | |
491 base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_); | |
492 } else { | |
468 #elif defined(OS_MACOSX) | 493 #elif defined(OS_MACOSX) |
469 if (known_dead) { | 494 if (known_dead) { |
470 context_->termination_status_ = | 495 context_->termination_status_ = |
471 base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_); | 496 base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_); |
472 } else | 497 } else { |
498 #elif defined(OS_ANDROID) | |
499 if (IsChildProcessOomProtected(handle)) { | |
500 context_->termination_status_ = base::TERMINATION_STATUS_OOM_PROTECTED; | |
501 } else { | |
502 #else | |
503 { | |
473 #endif | 504 #endif |
474 { | |
475 context_->termination_status_ = | 505 context_->termination_status_ = |
476 base::GetTerminationStatus(handle, &context_->exit_code_); | 506 base::GetTerminationStatus(handle, &context_->exit_code_); |
477 } | 507 } |
478 | 508 |
479 if (exit_code) | 509 if (exit_code) |
480 *exit_code = context_->exit_code_; | 510 *exit_code = context_->exit_code_; |
481 | 511 |
482 // POSIX: If the process crashed, then the kernel closed the socket | 512 // POSIX: If the process crashed, then the kernel closed the socket |
483 // for it and so the child has already died by the time we get | 513 // for it and so the child has already died by the time we get |
484 // here. Since GetTerminationStatus called waitpid with WNOHANG, | 514 // here. Since GetTerminationStatus called waitpid with WNOHANG, |
(...skipping 14 matching lines...) Expand all Loading... | |
499 GetHandle(), background)); | 529 GetHandle(), background)); |
500 } | 530 } |
501 | 531 |
502 void ChildProcessLauncher::SetTerminateChildOnShutdown( | 532 void ChildProcessLauncher::SetTerminateChildOnShutdown( |
503 bool terminate_on_shutdown) { | 533 bool terminate_on_shutdown) { |
504 if (context_.get()) | 534 if (context_.get()) |
505 context_->set_terminate_child_on_shutdown(terminate_on_shutdown); | 535 context_->set_terminate_child_on_shutdown(terminate_on_shutdown); |
506 } | 536 } |
507 | 537 |
508 } // namespace content | 538 } // namespace content |
OLD | NEW |