Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: content/browser/child_process_launcher.cc

Issue 1532423003: Have each SandboxedProcessLauncherDelegate maintain a zygote. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixup the namespace and header name. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 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> 7 #include <utility>
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 21 matching lines...) Expand all
32 #include "content/browser/bootstrap_sandbox_manager_mac.h" 32 #include "content/browser/bootstrap_sandbox_manager_mac.h"
33 #include "content/browser/mach_broker_mac.h" 33 #include "content/browser/mach_broker_mac.h"
34 #include "sandbox/mac/bootstrap_sandbox.h" 34 #include "sandbox/mac/bootstrap_sandbox.h"
35 #include "sandbox/mac/pre_exec_delegate.h" 35 #include "sandbox/mac/pre_exec_delegate.h"
36 #elif defined(OS_ANDROID) 36 #elif defined(OS_ANDROID)
37 #include "base/android/jni_android.h" 37 #include "base/android/jni_android.h"
38 #include "content/browser/android/child_process_launcher_android.h" 38 #include "content/browser/android/child_process_launcher_android.h"
39 #elif defined(OS_POSIX) 39 #elif defined(OS_POSIX)
40 #include "base/memory/singleton.h" 40 #include "base/memory/singleton.h"
41 #include "content/browser/renderer_host/render_sandbox_host_linux.h" 41 #include "content/browser/renderer_host/render_sandbox_host_linux.h"
42 #include "content/browser/zygote_host/zygote_communication_linux.h"
42 #include "content/browser/zygote_host/zygote_host_impl_linux.h" 43 #include "content/browser/zygote_host/zygote_host_impl_linux.h"
43 #include "content/common/child_process_sandbox_support_impl_linux.h" 44 #include "content/common/child_process_sandbox_support_impl_linux.h"
44 #endif 45 #endif
45 46
46 #if defined(OS_POSIX) 47 #if defined(OS_POSIX)
47 #include "base/posix/global_descriptors.h" 48 #include "base/posix/global_descriptors.h"
48 #include "content/browser/file_descriptor_info_impl.h" 49 #include "content/browser/file_descriptor_info_impl.h"
49 #include "gin/v8_initializer.h" 50 #include "gin/v8_initializer.h"
50 #endif 51 #endif
51 52
52 namespace content { 53 namespace content {
53 54
54 namespace { 55 namespace {
55 56
56 typedef base::Callback<void(bool, 57 typedef base::Callback<void(ZygoteHandle,
57 #if defined(OS_ANDROID) 58 #if defined(OS_ANDROID)
58 base::ScopedFD, 59 base::ScopedFD,
59 #endif 60 #endif
60 base::Process)> NotifyCallback; 61 base::Process)> NotifyCallback;
61 62
62 void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) { 63 void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) {
63 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 64 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
64 // Log the launch time, separating out the first one (which will likely be 65 // Log the launch time, separating out the first one (which will likely be
65 // slower due to the rest of the browser initializing at the same time). 66 // slower due to the rest of the browser initializing at the same time).
66 static bool done_first_launch = false; 67 static bool done_first_launch = false;
(...skipping 13 matching lines...) Expand all
80 const base::TimeTicks begin_launch_time, 81 const base::TimeTicks begin_launch_time,
81 base::ScopedFD ipcfd, 82 base::ScopedFD ipcfd,
82 base::ProcessHandle handle) { 83 base::ProcessHandle handle) {
83 // This can be called on the launcher thread or UI thread. 84 // This can be called on the launcher thread or UI thread.
84 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time; 85 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time;
85 BrowserThread::PostTask( 86 BrowserThread::PostTask(
86 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 87 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
87 base::Bind(&RecordHistogramsOnLauncherThread, launch_time)); 88 base::Bind(&RecordHistogramsOnLauncherThread, launch_time));
88 89
89 base::Closure callback_on_client_thread( 90 base::Closure callback_on_client_thread(
90 base::Bind(callback, false, base::Passed(&ipcfd), 91 base::Bind(callback, nullptr, base::Passed(&ipcfd),
91 base::Passed(base::Process(handle)))); 92 base::Passed(base::Process(handle))));
92 if (BrowserThread::CurrentlyOn(client_thread_id)) { 93 if (BrowserThread::CurrentlyOn(client_thread_id)) {
93 callback_on_client_thread.Run(); 94 callback_on_client_thread.Run();
94 } else { 95 } else {
95 BrowserThread::PostTask( 96 BrowserThread::PostTask(
96 client_thread_id, FROM_HERE, callback_on_client_thread); 97 client_thread_id, FROM_HERE, callback_on_client_thread);
97 } 98 }
98 } 99 }
99 #endif 100 #endif
100 101
101 void LaunchOnLauncherThread(const NotifyCallback& callback, 102 void LaunchOnLauncherThread(const NotifyCallback& callback,
102 BrowserThread::ID client_thread_id, 103 BrowserThread::ID client_thread_id,
103 int child_process_id, 104 int child_process_id,
104 SandboxedProcessLauncherDelegate* delegate, 105 SandboxedProcessLauncherDelegate* delegate,
105 #if defined(OS_ANDROID) 106 #if defined(OS_ANDROID)
106 base::ScopedFD ipcfd, 107 base::ScopedFD ipcfd,
107 #endif 108 #endif
108 base::CommandLine* cmd_line) { 109 base::CommandLine* cmd_line) {
109 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 110 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
110 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); 111 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
112 #if !defined(OS_ANDROID)
113 ZygoteHandle zygote = nullptr;
114 #endif
111 #if defined(OS_WIN) 115 #if defined(OS_WIN)
112 bool use_zygote = false;
113 bool launch_elevated = delegate->ShouldLaunchElevated(); 116 bool launch_elevated = delegate->ShouldLaunchElevated();
114 #elif defined(OS_MACOSX) 117 #elif defined(OS_MACOSX)
115 bool use_zygote = false;
116 base::EnvironmentMap env = delegate->GetEnvironment(); 118 base::EnvironmentMap env = delegate->GetEnvironment();
117 base::ScopedFD ipcfd = delegate->TakeIpcFd(); 119 base::ScopedFD ipcfd = delegate->TakeIpcFd();
118 #elif defined(OS_POSIX) && !defined(OS_ANDROID) 120 #elif defined(OS_POSIX) && !defined(OS_ANDROID)
119 bool use_zygote = delegate->ShouldUseZygote();
120 base::EnvironmentMap env = delegate->GetEnvironment(); 121 base::EnvironmentMap env = delegate->GetEnvironment();
121 base::ScopedFD ipcfd = delegate->TakeIpcFd(); 122 base::ScopedFD ipcfd = delegate->TakeIpcFd();
122 #endif 123 #endif
123 scoped_ptr<base::CommandLine> cmd_line_deleter(cmd_line); 124 scoped_ptr<base::CommandLine> cmd_line_deleter(cmd_line);
124 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); 125 base::TimeTicks begin_launch_time = base::TimeTicks::Now();
125 126
126 base::Process process; 127 base::Process process;
127 #if defined(OS_WIN) 128 #if defined(OS_WIN)
128 if (launch_elevated) { 129 if (launch_elevated) {
129 base::LaunchOptions options; 130 base::LaunchOptions options;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 StartChildProcess( 193 StartChildProcess(
193 cmd_line->argv(), child_process_id, std::move(files_to_register), regions, 194 cmd_line->argv(), child_process_id, std::move(files_to_register), regions,
194 base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id, 195 base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id,
195 begin_launch_time, base::Passed(&ipcfd))); 196 begin_launch_time, base::Passed(&ipcfd)));
196 197
197 #elif defined(OS_POSIX) 198 #elif defined(OS_POSIX)
198 // We need to close the client end of the IPC channel to reliably detect 199 // We need to close the client end of the IPC channel to reliably detect
199 // child termination. 200 // child termination.
200 201
201 #if !defined(OS_MACOSX) 202 #if !defined(OS_MACOSX)
202 if (use_zygote) { 203 ZygoteHandle* zygote_handle = delegate->GetZygote();
203 base::ProcessHandle handle = ZygoteHostImpl::GetInstance()->ForkRequest( 204 // If |zygote_handle| is null, a zygote should not be used.
205 if (zygote_handle) {
206 // This code runs on the PROCESS_LAUNCHER thread so race conditions are not
207 // an issue with the lazy initialization.
208 if (*zygote_handle == nullptr) {
Mark Seaborn 2016/01/19 21:06:43 So there is still this code for launching the zygo
mdempsky 2016/01/19 21:26:43 It's not currently used, but we'll start using it
Greg K 2016/01/19 22:20:16 I talked to Matt, except for NaCl, the zygotes are
209 *zygote_handle = new ZygoteCommunication();
210 (*zygote_handle)->Init();
211 }
212 zygote = *zygote_handle;
213 base::ProcessHandle handle = zygote->ForkRequest(
204 cmd_line->argv(), std::move(files_to_register), process_type); 214 cmd_line->argv(), std::move(files_to_register), process_type);
205 process = base::Process(handle); 215 process = base::Process(handle);
206 } else 216 } else
207 // Fall through to the normal posix case below when we're not zygoting. 217 // Fall through to the normal posix case below when we're not zygoting.
208 #endif // !defined(OS_MACOSX) 218 #endif // !defined(OS_MACOSX)
209 { 219 {
210 // Convert FD mapping to FileHandleMappingVector 220 // Convert FD mapping to FileHandleMappingVector
211 base::FileHandleMappingVector fds_to_map = 221 base::FileHandleMappingVector fds_to_map =
212 files_to_register->GetMappingWithIDAdjustment( 222 files_to_register->GetMappingWithIDAdjustment(
213 base::GlobalDescriptors::kBaseDescriptor); 223 base::GlobalDescriptors::kBaseDescriptor);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 broker->GetLock().Release(); 282 broker->GetLock().Release();
273 #endif // defined(OS_MACOSX) 283 #endif // defined(OS_MACOSX)
274 } 284 }
275 #endif // else defined(OS_POSIX) 285 #endif // else defined(OS_POSIX)
276 #if !defined(OS_ANDROID) 286 #if !defined(OS_ANDROID)
277 if (process.IsValid()) { 287 if (process.IsValid()) {
278 RecordHistogramsOnLauncherThread(base::TimeTicks::Now() - 288 RecordHistogramsOnLauncherThread(base::TimeTicks::Now() -
279 begin_launch_time); 289 begin_launch_time);
280 } 290 }
281 BrowserThread::PostTask(client_thread_id, FROM_HERE, 291 BrowserThread::PostTask(client_thread_id, FROM_HERE,
282 base::Bind(callback, 292 base::Bind(callback, zygote, base::Passed(&process)));
283 use_zygote,
284 base::Passed(&process)));
285 #endif // !defined(OS_ANDROID) 293 #endif // !defined(OS_ANDROID)
286 } 294 }
287 295
288 void TerminateOnLauncherThread(bool zygote, base::Process process) { 296 void TerminateOnLauncherThread(ZygoteHandle zygote, base::Process process) {
289 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 297 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
290 #if defined(OS_ANDROID) 298 #if defined(OS_ANDROID)
291 VLOG(1) << "ChromeProcess: Stopping process with handle " 299 VLOG(1) << "ChromeProcess: Stopping process with handle "
292 << process.Handle(); 300 << process.Handle();
293 StopChildProcess(process.Handle()); 301 StopChildProcess(process.Handle());
294 #else 302 #else
295 // Client has gone away, so just kill the process. Using exit code 0 303 // Client has gone away, so just kill the process. Using exit code 0
296 // means that UMA won't treat this as a crash. 304 // means that UMA won't treat this as a crash.
297 process.Terminate(RESULT_CODE_NORMAL_EXIT, false); 305 process.Terminate(RESULT_CODE_NORMAL_EXIT, false);
298 // On POSIX, we must additionally reap the child. 306 // On POSIX, we must additionally reap the child.
299 #if defined(OS_POSIX) 307 #if defined(OS_POSIX)
300 #if !defined(OS_MACOSX) 308 #if !defined(OS_MACOSX)
301 if (zygote) { 309 if (zygote) {
302 // If the renderer was created via a zygote, we have to proxy the reaping 310 // If the renderer was created via a zygote, we have to proxy the reaping
303 // through the zygote process. 311 // through the zygote process.
304 ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(process.Handle()); 312 zygote->EnsureProcessTerminated(process.Handle());
305 } else 313 } else
306 #endif // !OS_MACOSX 314 #endif // !OS_MACOSX
307 base::EnsureProcessTerminated(std::move(process)); 315 base::EnsureProcessTerminated(std::move(process));
308 #endif // OS_POSIX 316 #endif // OS_POSIX
309 #endif // defined(OS_ANDROID) 317 #endif // defined(OS_ANDROID)
310 } 318 }
311 319
312 void SetProcessBackgroundedOnLauncherThread(base::Process process, 320 void SetProcessBackgroundedOnLauncherThread(base::Process process,
313 bool background) { 321 bool background) {
314 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 322 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
315 if (process.CanBackgroundProcesses()) { 323 if (process.CanBackgroundProcesses()) {
316 process.SetProcessBackgrounded(background); 324 process.SetProcessBackgrounded(background);
317 } 325 }
318 #if defined(OS_ANDROID) 326 #if defined(OS_ANDROID)
319 SetChildProcessInForeground(process.Handle(), !background); 327 SetChildProcessInForeground(process.Handle(), !background);
320 #endif 328 #endif
321 } 329 }
322 330
323 } // namespace 331 } // namespace
324 332
325 ChildProcessLauncher::ChildProcessLauncher( 333 ChildProcessLauncher::ChildProcessLauncher(
326 SandboxedProcessLauncherDelegate* delegate, 334 SandboxedProcessLauncherDelegate* delegate,
327 base::CommandLine* cmd_line, 335 base::CommandLine* cmd_line,
328 int child_process_id, 336 int child_process_id,
329 Client* client, 337 Client* client,
330 bool terminate_on_shutdown) 338 bool terminate_on_shutdown)
331 : client_(client), 339 : client_(client),
332 termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION), 340 termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
333 exit_code_(RESULT_CODE_NORMAL_EXIT), 341 exit_code_(RESULT_CODE_NORMAL_EXIT),
334 zygote_(false), 342 zygote_(nullptr),
335 starting_(true), 343 starting_(true),
336 #if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \ 344 #if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
337 defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \ 345 defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
338 defined(UNDEFINED_SANITIZER) 346 defined(UNDEFINED_SANITIZER)
339 terminate_child_on_shutdown_(false), 347 terminate_child_on_shutdown_(false),
340 #else 348 #else
341 terminate_child_on_shutdown_(terminate_on_shutdown), 349 terminate_child_on_shutdown_(terminate_on_shutdown),
342 #endif 350 #endif
343 weak_factory_(this) { 351 weak_factory_(this) {
344 DCHECK(CalledOnValidThread()); 352 DCHECK(CalledOnValidThread());
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 #if defined(OS_ANDROID) 402 #if defined(OS_ANDROID)
395 base::Passed(&ipcfd), 403 base::Passed(&ipcfd),
396 #endif 404 #endif
397 cmd_line)); 405 cmd_line));
398 } 406 }
399 407
400 void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) { 408 void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) {
401 DCHECK(CalledOnValidThread()); 409 DCHECK(CalledOnValidThread());
402 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 410 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
403 if (zygote_) { 411 if (zygote_) {
404 termination_status_ = ZygoteHostImpl::GetInstance()-> 412 termination_status_ = zygote_->GetTerminationStatus(
405 GetTerminationStatus(process_.Handle(), known_dead, &exit_code_); 413 process_.Handle(), known_dead, &exit_code_);
406 } else if (known_dead) { 414 } else if (known_dead) {
407 termination_status_ = 415 termination_status_ =
408 base::GetKnownDeadTerminationStatus(process_.Handle(), &exit_code_); 416 base::GetKnownDeadTerminationStatus(process_.Handle(), &exit_code_);
409 } else { 417 } else {
410 #elif defined(OS_MACOSX) 418 #elif defined(OS_MACOSX)
411 if (known_dead) { 419 if (known_dead) {
412 termination_status_ = 420 termination_status_ =
413 base::GetKnownDeadTerminationStatus(process_.Handle(), &exit_code_); 421 base::GetKnownDeadTerminationStatus(process_.Handle(), &exit_code_);
414 } else { 422 } else {
415 #elif defined(OS_ANDROID) 423 #elif defined(OS_ANDROID)
(...skipping 12 matching lines...) Expand all
428 DCHECK(CalledOnValidThread()); 436 DCHECK(CalledOnValidThread());
429 base::Process to_pass = process_.Duplicate(); 437 base::Process to_pass = process_.Duplicate();
430 BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 438 BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
431 base::Bind(&SetProcessBackgroundedOnLauncherThread, 439 base::Bind(&SetProcessBackgroundedOnLauncherThread,
432 base::Passed(&to_pass), background)); 440 base::Passed(&to_pass), background));
433 } 441 }
434 442
435 void ChildProcessLauncher::DidLaunch( 443 void ChildProcessLauncher::DidLaunch(
436 base::WeakPtr<ChildProcessLauncher> instance, 444 base::WeakPtr<ChildProcessLauncher> instance,
437 bool terminate_on_shutdown, 445 bool terminate_on_shutdown,
438 bool zygote, 446 ZygoteHandle zygote,
439 #if defined(OS_ANDROID) 447 #if defined(OS_ANDROID)
440 base::ScopedFD ipcfd, 448 base::ScopedFD ipcfd,
441 #endif 449 #endif
442 base::Process process) { 450 base::Process process) {
443 if (!process.IsValid()) 451 if (!process.IsValid())
444 LOG(ERROR) << "Failed to launch child process"; 452 LOG(ERROR) << "Failed to launch child process";
445 453
446 if (instance.get()) { 454 if (instance.get()) {
447 instance->Notify(zygote, 455 instance->Notify(zygote,
448 #if defined(OS_ANDROID) 456 #if defined(OS_ANDROID)
449 std::move(ipcfd), 457 std::move(ipcfd),
450 #endif 458 #endif
451 std::move(process)); 459 std::move(process));
452 } else { 460 } else {
453 if (process.IsValid() && terminate_on_shutdown) { 461 if (process.IsValid() && terminate_on_shutdown) {
454 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So 462 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So
455 // don't this on the UI/IO threads. 463 // don't this on the UI/IO threads.
456 BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 464 BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
457 base::Bind(&TerminateOnLauncherThread, zygote, 465 base::Bind(&TerminateOnLauncherThread, zygote,
458 base::Passed(&process))); 466 base::Passed(&process)));
459 } 467 }
460 } 468 }
461 } 469 }
462 470
463 void ChildProcessLauncher::Notify( 471 void ChildProcessLauncher::Notify(ZygoteHandle zygote,
464 bool zygote,
465 #if defined(OS_ANDROID) 472 #if defined(OS_ANDROID)
466 base::ScopedFD ipcfd, 473 base::ScopedFD ipcfd,
467 #endif 474 #endif
468 base::Process process) { 475 base::Process process) {
469 DCHECK(CalledOnValidThread()); 476 DCHECK(CalledOnValidThread());
470 starting_ = false; 477 starting_ = false;
471 process_ = std::move(process); 478 process_ = std::move(process);
472 479
473 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 480 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
474 zygote_ = zygote; 481 zygote_ = zygote;
475 #endif 482 #endif
476 if (process_.IsValid()) { 483 if (process_.IsValid()) {
477 client_->OnProcessLaunched(); 484 client_->OnProcessLaunched();
478 } else { 485 } else {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 } 528 }
522 529
523 ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest( 530 ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
524 Client* client) { 531 Client* client) {
525 Client* ret = client_; 532 Client* ret = client_;
526 client_ = client; 533 client_ = client;
527 return ret; 534 return ret;
528 } 535 }
529 536
530 } // namespace content 537 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698