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

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

Powered by Google App Engine
This is Rietveld 408576698