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

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

Issue 1923653002: Wire up process launch error codes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix debug and clang Created 4 years, 7 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 <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 15 matching lines...) Expand all
26 #include "content/public/common/sandboxed_process_launcher_delegate.h" 26 #include "content/public/common/sandboxed_process_launcher_delegate.h"
27 #include "mojo/edk/embedder/embedder.h" 27 #include "mojo/edk/embedder/embedder.h"
28 #include "mojo/edk/embedder/scoped_platform_handle.h" 28 #include "mojo/edk/embedder/scoped_platform_handle.h"
29 29
30 #if defined(OS_WIN) 30 #if defined(OS_WIN)
31 #include "base/files/file_path.h" 31 #include "base/files/file_path.h"
32 #include "base/win/scoped_handle.h" 32 #include "base/win/scoped_handle.h"
33 #include "base/win/win_util.h" 33 #include "base/win/win_util.h"
34 #include "content/common/sandbox_win.h" 34 #include "content/common/sandbox_win.h"
35 #include "content/public/common/sandbox_init.h" 35 #include "content/public/common/sandbox_init.h"
36 #include "sandbox/win/src/sandbox_types.h"
36 #elif defined(OS_MACOSX) 37 #elif defined(OS_MACOSX)
37 #include "content/browser/bootstrap_sandbox_manager_mac.h" 38 #include "content/browser/bootstrap_sandbox_manager_mac.h"
38 #include "content/browser/mach_broker_mac.h" 39 #include "content/browser/mach_broker_mac.h"
39 #include "sandbox/mac/bootstrap_sandbox.h" 40 #include "sandbox/mac/bootstrap_sandbox.h"
40 #include "sandbox/mac/pre_exec_delegate.h" 41 #include "sandbox/mac/pre_exec_delegate.h"
41 #elif defined(OS_ANDROID) 42 #elif defined(OS_ANDROID)
42 #include "base/android/jni_android.h" 43 #include "base/android/jni_android.h"
43 #include "content/browser/android/child_process_launcher_android.h" 44 #include "content/browser/android/child_process_launcher_android.h"
44 #elif defined(OS_POSIX) 45 #elif defined(OS_POSIX)
45 #include "base/memory/singleton.h" 46 #include "base/memory/singleton.h"
(...skipping 12 matching lines...) Expand all
58 59
59 namespace content { 60 namespace content {
60 61
61 namespace { 62 namespace {
62 63
63 typedef base::Callback<void(ZygoteHandle, 64 typedef base::Callback<void(ZygoteHandle,
64 #if defined(OS_ANDROID) 65 #if defined(OS_ANDROID)
65 base::ScopedFD, 66 base::ScopedFD,
66 base::ScopedFD, 67 base::ScopedFD,
67 #endif 68 #endif
68 base::Process)> NotifyCallback; 69 base::Process,
70 int)> NotifyCallback;
69 71
70 void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) { 72 void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) {
71 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 73 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
72 // Log the launch time, separating out the first one (which will likely be 74 // Log the launch time, separating out the first one (which will likely be
73 // slower due to the rest of the browser initializing at the same time). 75 // slower due to the rest of the browser initializing at the same time).
74 static bool done_first_launch = false; 76 static bool done_first_launch = false;
75 if (done_first_launch) { 77 if (done_first_launch) {
76 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time); 78 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time);
77 } else { 79 } else {
78 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchFirst", launch_time); 80 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchFirst", launch_time);
79 done_first_launch = true; 81 done_first_launch = true;
80 } 82 }
81 } 83 }
82 84
83 #if defined(OS_ANDROID) 85 #if defined(OS_ANDROID)
84 // TODO(sievers): Remove this by defining better what happens on what 86 // TODO(sievers): Remove this by defining better what happens on what
85 // thread in the corresponding Java code. 87 // thread in the corresponding Java code.
86 void OnChildProcessStartedAndroid(const NotifyCallback& callback, 88 void OnChildProcessStartedAndroid(const NotifyCallback& callback,
87 BrowserThread::ID client_thread_id, 89 BrowserThread::ID client_thread_id,
88 const base::TimeTicks begin_launch_time, 90 const base::TimeTicks begin_launch_time,
89 base::ScopedFD ipcfd, 91 base::ScopedFD ipcfd,
90 base::ScopedFD mojo_fd, 92 base::ScopedFD mojo_fd,
91 base::ProcessHandle handle) { 93 base::ProcessHandle handle) {
94 int launch_result = (handle == base::kNullProcessHandle)
95 ? LAUNCH_RESULT_FAILURE
96 : LAUNCH_RESULT_SUCCESS;
92 // This can be called on the launcher thread or UI thread. 97 // This can be called on the launcher thread or UI thread.
93 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time; 98 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time;
94 BrowserThread::PostTask( 99 BrowserThread::PostTask(
95 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 100 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
96 base::Bind(&RecordHistogramsOnLauncherThread, launch_time)); 101 base::Bind(&RecordHistogramsOnLauncherThread, launch_time));
97 102
98 base::Closure callback_on_client_thread( 103 base::Closure callback_on_client_thread(base::Bind(
99 base::Bind(callback, nullptr, base::Passed(&ipcfd), 104 callback, nullptr, base::Passed(&ipcfd), base::Passed(&mojo_fd),
100 base::Passed(&mojo_fd), base::Passed(base::Process(handle)))); 105 base::Passed(base::Process(handle)), launch_result));
101 if (BrowserThread::CurrentlyOn(client_thread_id)) { 106 if (BrowserThread::CurrentlyOn(client_thread_id)) {
102 callback_on_client_thread.Run(); 107 callback_on_client_thread.Run();
103 } else { 108 } else {
104 BrowserThread::PostTask( 109 BrowserThread::PostTask(
105 client_thread_id, FROM_HERE, callback_on_client_thread); 110 client_thread_id, FROM_HERE, callback_on_client_thread);
106 } 111 }
107 } 112 }
108 #endif 113 #endif
109 114
110 void LaunchOnLauncherThread(const NotifyCallback& callback, 115 void LaunchOnLauncherThread(const NotifyCallback& callback,
111 BrowserThread::ID client_thread_id, 116 BrowserThread::ID client_thread_id,
112 int child_process_id, 117 int child_process_id,
113 SandboxedProcessLauncherDelegate* delegate, 118 SandboxedProcessLauncherDelegate* delegate,
114 #if defined(OS_ANDROID) 119 #if defined(OS_ANDROID)
115 base::ScopedFD ipcfd, 120 base::ScopedFD ipcfd,
116 #endif 121 #endif
117 mojo::edk::ScopedPlatformHandle client_handle, 122 mojo::edk::ScopedPlatformHandle client_handle,
118 base::CommandLine* cmd_line) { 123 base::CommandLine* cmd_line) {
119 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 124 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
120 std::unique_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); 125 std::unique_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
121 #if !defined(OS_ANDROID) 126 #if !defined(OS_ANDROID)
122 ZygoteHandle zygote = nullptr; 127 ZygoteHandle zygote = nullptr;
128 int launch_result = LAUNCH_RESULT_FAILURE;
123 #endif 129 #endif
124 #if defined(OS_WIN) 130 #if defined(OS_WIN)
125 bool launch_elevated = delegate->ShouldLaunchElevated(); 131 bool launch_elevated = delegate->ShouldLaunchElevated();
126 #elif defined(OS_MACOSX) 132 #elif defined(OS_MACOSX)
127 base::EnvironmentMap env = delegate->GetEnvironment(); 133 base::EnvironmentMap env = delegate->GetEnvironment();
128 base::ScopedFD ipcfd = delegate->TakeIpcFd(); 134 base::ScopedFD ipcfd = delegate->TakeIpcFd();
129 #elif defined(OS_POSIX) && !defined(OS_ANDROID) 135 #elif defined(OS_POSIX) && !defined(OS_ANDROID)
130 base::EnvironmentMap env = delegate->GetEnvironment(); 136 base::EnvironmentMap env = delegate->GetEnvironment();
131 base::ScopedFD ipcfd = delegate->TakeIpcFd(); 137 base::ScopedFD ipcfd = delegate->TakeIpcFd();
132 #endif 138 #endif
133 std::unique_ptr<base::CommandLine> cmd_line_deleter(cmd_line); 139 std::unique_ptr<base::CommandLine> cmd_line_deleter(cmd_line);
134 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); 140 base::TimeTicks begin_launch_time = base::TimeTicks::Now();
135 141
136 base::Process process; 142 base::Process process;
137 #if defined(OS_WIN) 143 #if defined(OS_WIN)
138 if (launch_elevated) { 144 if (launch_elevated) {
139 // TODO(rockot): We may want to support Mojo IPC to elevated processes as 145 // TODO(rockot): We may want to support Mojo IPC to elevated processes as
140 // well, but this isn't currently feasible without sharing a pipe path on 146 // well, but this isn't currently feasible without sharing a pipe path on
141 // the command line as elevated process launch goes through ShellExecuteEx. 147 // the command line as elevated process launch goes through ShellExecuteEx.
142 base::LaunchOptions options; 148 base::LaunchOptions options;
143 options.start_hidden = true; 149 options.start_hidden = true;
144 process = base::LaunchElevatedProcess(*cmd_line, options); 150 process = base::LaunchElevatedProcess(*cmd_line, options);
145 } else { 151 } else {
146 base::HandlesToInheritVector handles; 152 base::HandlesToInheritVector handles;
147 handles.push_back(client_handle.get().handle); 153 handles.push_back(client_handle.get().handle);
148 cmd_line->AppendSwitchASCII( 154 cmd_line->AppendSwitchASCII(
149 mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch, 155 mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch,
150 base::UintToString(base::win::HandleToUint32(handles[0]))); 156 base::UintToString(base::win::HandleToUint32(handles[0])));
151 process = StartSandboxedProcess(delegate, cmd_line, handles); 157 launch_result =
158 StartSandboxedProcess(delegate, cmd_line, handles, &process);
152 } 159 }
153 #elif defined(OS_POSIX) 160 #elif defined(OS_POSIX)
154 std::string process_type = 161 std::string process_type =
155 cmd_line->GetSwitchValueASCII(switches::kProcessType); 162 cmd_line->GetSwitchValueASCII(switches::kProcessType);
156 std::unique_ptr<FileDescriptorInfo> files_to_register( 163 std::unique_ptr<FileDescriptorInfo> files_to_register(
157 FileDescriptorInfoImpl::Create()); 164 FileDescriptorInfoImpl::Create());
158 165
159 base::ScopedFD mojo_fd(client_handle.release().handle); 166 base::ScopedFD mojo_fd(client_handle.release().handle);
160 DCHECK(mojo_fd.is_valid()); 167 DCHECK(mojo_fd.is_valid());
161 168
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 } 335 }
329 336
330 // After updating the broker, release the lock and let the child's 337 // After updating the broker, release the lock and let the child's
331 // messasge be processed on the broker's thread. 338 // messasge be processed on the broker's thread.
332 broker->GetLock().Release(); 339 broker->GetLock().Release();
333 #endif // defined(OS_MACOSX) 340 #endif // defined(OS_MACOSX)
334 } 341 }
335 #endif // else defined(OS_POSIX) 342 #endif // else defined(OS_POSIX)
336 #if !defined(OS_ANDROID) 343 #if !defined(OS_ANDROID)
337 if (process.IsValid()) { 344 if (process.IsValid()) {
345 launch_result = LAUNCH_RESULT_SUCCESS;
338 RecordHistogramsOnLauncherThread(base::TimeTicks::Now() - 346 RecordHistogramsOnLauncherThread(base::TimeTicks::Now() -
339 begin_launch_time); 347 begin_launch_time);
340 } 348 }
341 BrowserThread::PostTask(client_thread_id, FROM_HERE, 349 BrowserThread::PostTask(client_thread_id, FROM_HERE,
342 base::Bind(callback, zygote, base::Passed(&process))); 350 base::Bind(callback, zygote, base::Passed(&process),
351 launch_result));
343 #endif // !defined(OS_ANDROID) 352 #endif // !defined(OS_ANDROID)
344 } 353 }
345 354
346 void TerminateOnLauncherThread(ZygoteHandle zygote, base::Process process) { 355 void TerminateOnLauncherThread(ZygoteHandle zygote, base::Process process) {
347 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 356 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
348 #if defined(OS_ANDROID) 357 #if defined(OS_ANDROID)
349 VLOG(1) << "ChromeProcess: Stopping process with handle " 358 VLOG(1) << "ChromeProcess: Stopping process with handle "
350 << process.Handle(); 359 << process.Handle();
351 StopChildProcess(process.Handle()); 360 StopChildProcess(process.Handle());
352 #else 361 #else
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 } 502 }
494 503
495 void ChildProcessLauncher::DidLaunch( 504 void ChildProcessLauncher::DidLaunch(
496 base::WeakPtr<ChildProcessLauncher> instance, 505 base::WeakPtr<ChildProcessLauncher> instance,
497 bool terminate_on_shutdown, 506 bool terminate_on_shutdown,
498 ZygoteHandle zygote, 507 ZygoteHandle zygote,
499 #if defined(OS_ANDROID) 508 #if defined(OS_ANDROID)
500 base::ScopedFD ipcfd, 509 base::ScopedFD ipcfd,
501 base::ScopedFD mojo_fd, 510 base::ScopedFD mojo_fd,
502 #endif 511 #endif
503 base::Process process) { 512 base::Process process,
513 int error_code) {
504 if (!process.IsValid()) 514 if (!process.IsValid())
505 LOG(ERROR) << "Failed to launch child process"; 515 LOG(ERROR) << "Failed to launch child process";
506 516
507 if (instance.get()) { 517 if (instance.get()) {
508 instance->Notify(zygote, 518 instance->Notify(zygote,
509 #if defined(OS_ANDROID) 519 #if defined(OS_ANDROID)
510 std::move(ipcfd), 520 std::move(ipcfd),
511 #endif 521 #endif
512 std::move(process)); 522 std::move(process),
523 error_code);
513 } else { 524 } else {
514 if (process.IsValid() && terminate_on_shutdown) { 525 if (process.IsValid() && terminate_on_shutdown) {
515 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So 526 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So
516 // don't this on the UI/IO threads. 527 // don't this on the UI/IO threads.
517 BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 528 BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
518 base::Bind(&TerminateOnLauncherThread, zygote, 529 base::Bind(&TerminateOnLauncherThread, zygote,
519 base::Passed(&process))); 530 base::Passed(&process)));
520 } 531 }
521 } 532 }
522 } 533 }
523 534
524 void ChildProcessLauncher::Notify(ZygoteHandle zygote, 535 void ChildProcessLauncher::Notify(ZygoteHandle zygote,
525 #if defined(OS_ANDROID) 536 #if defined(OS_ANDROID)
526 base::ScopedFD ipcfd, 537 base::ScopedFD ipcfd,
527 #endif 538 #endif
528 base::Process process) { 539 base::Process process,
540 int error_code) {
529 DCHECK(CalledOnValidThread()); 541 DCHECK(CalledOnValidThread());
530 starting_ = false; 542 starting_ = false;
531 process_ = std::move(process); 543 process_ = std::move(process);
532 544
533 if (process_.IsValid()) { 545 if (process_.IsValid()) {
534 // Set up Mojo IPC to the new process. 546 // Set up Mojo IPC to the new process.
535 mojo::edk::ChildProcessLaunched(process_.Handle(), 547 mojo::edk::ChildProcessLaunched(process_.Handle(),
536 mojo_platform_channel_.PassServerHandle()); 548 mojo_platform_channel_.PassServerHandle());
537 } 549 }
538 550
539 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 551 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
540 zygote_ = zygote; 552 zygote_ = zygote;
541 #endif 553 #endif
542 if (process_.IsValid()) { 554 if (process_.IsValid()) {
543 client_->OnProcessLaunched(); 555 client_->OnProcessLaunched();
544 } else { 556 } else {
545 termination_status_ = base::TERMINATION_STATUS_LAUNCH_FAILED; 557 termination_status_ = base::TERMINATION_STATUS_LAUNCH_FAILED;
546 client_->OnProcessLaunchFailed(); 558 client_->OnProcessLaunchFailed(error_code);
547 } 559 }
548 } 560 }
549 561
550 bool ChildProcessLauncher::IsStarting() { 562 bool ChildProcessLauncher::IsStarting() {
551 // TODO(crbug.com/469248): This fails in some tests. 563 // TODO(crbug.com/469248): This fails in some tests.
552 // DCHECK(CalledOnValidThread()); 564 // DCHECK(CalledOnValidThread());
553 return starting_; 565 return starting_;
554 } 566 }
555 567
556 const base::Process& ChildProcessLauncher::GetProcess() const { 568 const base::Process& ChildProcessLauncher::GetProcess() const {
(...skipping 30 matching lines...) Expand all
587 } 599 }
588 600
589 ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest( 601 ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
590 Client* client) { 602 Client* client) {
591 Client* ret = client_; 603 Client* ret = client_;
592 client_ = client; 604 client_ = client;
593 return ret; 605 return ret;
594 } 606 }
595 607
596 } // namespace content 608 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/child_process_launcher.h ('k') | content/browser/child_process_launcher_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698