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

Unified Diff: content/browser/child_process_launcher.cc

Issue 2594203004: Unifying ChildProcessLauncher across platforms. (Closed)
Patch Set: Fixed Mac tests. Created 3 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/child_process_launcher.cc
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc
index 51f5696d31456265c29fc75933f95628aada588b..434fae7b2315c375647810bec18fdf93bedad9b3 100644
--- a/content/browser/child_process_launcher.cc
+++ b/content/browser/child_process_launcher.cc
@@ -4,75 +4,23 @@
#include "content/browser/child_process_launcher.h"
-#include <memory>
-#include <utility>
-
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/i18n/icu_util.h"
#include "base/logging.h"
-#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/launch.h"
-#include "base/process/process.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread.h"
#include "build/build_config.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/common/content_descriptors.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/named_platform_channel_pair.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "ppapi/features/features.h"
-
-#if defined(OS_WIN)
-#include "base/files/file_path.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/win_util.h"
-#include "content/common/sandbox_win.h"
-#include "content/public/common/sandbox_init.h"
-#include "sandbox/win/src/sandbox_types.h"
-#elif defined(OS_MACOSX)
-#include "content/browser/bootstrap_sandbox_manager_mac.h"
-#include "content/browser/mach_broker_mac.h"
-#include "sandbox/mac/bootstrap_sandbox.h"
-#include "sandbox/mac/pre_exec_delegate.h"
-#elif defined(OS_ANDROID)
-#include "base/android/jni_android.h"
-#include "content/browser/android/child_process_launcher_android.h"
-#elif defined(OS_POSIX)
-#include "base/memory/singleton.h"
-#include "content/browser/renderer_host/render_sandbox_host_linux.h"
-#include "content/browser/zygote_host/zygote_communication_linux.h"
-#include "content/browser/zygote_host/zygote_host_impl_linux.h"
-#include "content/common/child_process_sandbox_support_impl_linux.h"
-#include "content/public/browser/zygote_handle_linux.h"
-#endif
-
-#if defined(OS_POSIX)
-#include "base/posix/global_descriptors.h"
-#include "content/browser/file_descriptor_info_impl.h"
-#include "gin/v8_initializer.h"
-#endif
namespace content {
namespace {
-typedef base::Callback<void(ZygoteHandle,
-#if defined(OS_ANDROID)
- base::ScopedFD,
-#endif
- base::Process,
- int)>
- NotifyCallback;
-
void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) {
DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
// Log the launch time, separating out the first one (which will likely be
@@ -86,304 +34,11 @@ void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) {
}
}
-#if defined(OS_ANDROID)
-// TODO(sievers): Remove this by defining better what happens on what
-// thread in the corresponding Java code.
-void OnChildProcessStartedAndroid(const NotifyCallback& callback,
- BrowserThread::ID client_thread_id,
- const base::TimeTicks begin_launch_time,
- base::ScopedFD mojo_fd,
- base::ProcessHandle handle) {
- int launch_result = (handle == base::kNullProcessHandle)
- ? LAUNCH_RESULT_FAILURE
- : LAUNCH_RESULT_SUCCESS;
- // This can be called on the launcher thread or UI thread.
- base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time;
- BrowserThread::PostTask(
- BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
- base::Bind(&RecordHistogramsOnLauncherThread, launch_time));
-
- base::Closure callback_on_client_thread(
- base::Bind(callback, nullptr, base::Passed(&mojo_fd),
- base::Passed(base::Process(handle)), launch_result));
- if (BrowserThread::CurrentlyOn(client_thread_id)) {
- callback_on_client_thread.Run();
- } else {
- BrowserThread::PostTask(
- client_thread_id, FROM_HERE, callback_on_client_thread);
- }
-}
-#endif
-
-void LaunchOnLauncherThread(
- const NotifyCallback& callback,
- BrowserThread::ID client_thread_id,
- int child_process_id,
- std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
- mojo::edk::ScopedPlatformHandle client_handle,
- std::unique_ptr<base::CommandLine> cmd_line) {
- DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
-#if !defined(OS_ANDROID)
- ZygoteHandle zygote = nullptr;
- int launch_result = LAUNCH_RESULT_FAILURE;
-#endif
-#if defined(OS_WIN)
- bool launch_elevated = delegate->ShouldLaunchElevated();
-#elif defined(OS_MACOSX)
- base::EnvironmentMap env = delegate->GetEnvironment();
-#elif defined(OS_POSIX) && !defined(OS_ANDROID)
- base::EnvironmentMap env = delegate->GetEnvironment();
-#endif
- base::TimeTicks begin_launch_time = base::TimeTicks::Now();
-
- base::Process process;
-#if defined(OS_WIN)
- if (launch_elevated) {
- // When establishing a Mojo connection, the pipe path has already been added
- // to the command line.
- base::LaunchOptions options;
- options.start_hidden = true;
- process = base::LaunchElevatedProcess(*cmd_line, options);
- } else {
- base::HandlesToInheritVector handles;
- handles.push_back(client_handle.get().handle);
- base::FieldTrialList::AppendFieldTrialHandleIfNeeded(&handles);
- cmd_line->AppendSwitchASCII(
- mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch,
- base::UintToString(base::win::HandleToUint32(handles[0])));
- launch_result = StartSandboxedProcess(
- delegate.get(), cmd_line.get(), handles, &process);
- }
-#elif defined(OS_POSIX)
- std::string process_type =
- cmd_line->GetSwitchValueASCII(switches::kProcessType);
- std::unique_ptr<FileDescriptorInfo> files_to_register(
- FileDescriptorInfoImpl::Create());
-
- base::ScopedFD mojo_fd(client_handle.release().handle);
- DCHECK(mojo_fd.is_valid());
-
- int field_trial_handle = base::FieldTrialList::GetFieldTrialHandle();
- if (field_trial_handle != base::kInvalidPlatformFile)
- files_to_register->Share(kFieldTrialDescriptor, field_trial_handle);
-#if defined(OS_ANDROID)
- files_to_register->Share(kMojoIPCChannel, mojo_fd.get());
-#else
- files_to_register->Transfer(kMojoIPCChannel, std::move(mojo_fd));
-#endif
-#endif
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
- GetContentClient()->browser()->GetAdditionalMappedFilesForChildProcess(
- *cmd_line, child_process_id, files_to_register.get());
-#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
- bool snapshot_loaded = false;
- base::MemoryMappedFile::Region region;
-#if defined(OS_ANDROID)
- auto maybe_register = [&region, &files_to_register](int key, int fd) {
- if (fd != -1)
- files_to_register->ShareWithRegion(key, fd, region);
- };
- maybe_register(
- kV8NativesDataDescriptor,
- gin::V8Initializer::GetOpenNativesFileForChildProcesses(&region));
- maybe_register(
- kV8SnapshotDataDescriptor32,
- gin::V8Initializer::GetOpenSnapshotFileForChildProcesses(&region, true));
- maybe_register(
- kV8SnapshotDataDescriptor64,
- gin::V8Initializer::GetOpenSnapshotFileForChildProcesses(&region, false));
-
- snapshot_loaded = true;
-#else
- base::PlatformFile natives_pf =
- gin::V8Initializer::GetOpenNativesFileForChildProcesses(&region);
- DCHECK_GE(natives_pf, 0);
- files_to_register->ShareWithRegion(
- kV8NativesDataDescriptor, natives_pf, region);
-
- base::PlatformFile snapshot_pf =
- gin::V8Initializer::GetOpenSnapshotFileForChildProcesses(&region);
- // Failure to load the V8 snapshot is not necessarily an error. V8 can start
- // up (slower) without the snapshot.
- if (snapshot_pf != -1) {
- snapshot_loaded = true;
- files_to_register->ShareWithRegion(
- kV8SnapshotDataDescriptor, snapshot_pf, region);
- }
-#endif
-
- if (process_type != switches::kZygoteProcess) {
- cmd_line->AppendSwitch(::switches::kV8NativesPassedByFD);
- if (snapshot_loaded) {
- cmd_line->AppendSwitch(::switches::kV8SnapshotPassedByFD);
- }
- }
-#endif // defined(V8_USE_EXTERNAL_STARTUP_DATA)
-#endif // defined(OS_POSIX) && !defined(OS_MACOSX)
-
-#if defined(OS_ANDROID)
-#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
- base::MemoryMappedFile::Region icu_region;
- base::PlatformFile icu_pf = base::i18n::GetIcuDataFileHandle(&icu_region);
- files_to_register->ShareWithRegion(
- kAndroidICUDataDescriptor, icu_pf, icu_region);
-#endif // ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
-
- // Android WebView runs in single process, ensure that we never get here
- // when running in single process mode.
- CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
-
- StartChildProcess(
- cmd_line->argv(), child_process_id, std::move(files_to_register),
- base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id,
- begin_launch_time, base::Passed(&mojo_fd)));
-
-#elif defined(OS_POSIX)
- // We need to close the client end of the IPC channel to reliably detect
- // child termination.
-
-#if !defined(OS_MACOSX)
- ZygoteHandle* zygote_handle =
- !base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoZygote)
- ? delegate->GetZygote()
- : nullptr;
- // If |zygote_handle| is null, a zygote should not be used.
- if (zygote_handle) {
- // This code runs on the PROCESS_LAUNCHER thread so race conditions are not
- // an issue with the lazy initialization.
- if (*zygote_handle == nullptr) {
- *zygote_handle = CreateZygote();
- }
- zygote = *zygote_handle;
- base::ProcessHandle handle = zygote->ForkRequest(
- cmd_line->argv(), std::move(files_to_register), process_type);
- process = base::Process(handle);
- } else
- // Fall through to the normal posix case below when we're not zygoting.
-#endif // !defined(OS_MACOSX)
- {
- // Convert FD mapping to FileHandleMappingVector
- base::FileHandleMappingVector fds_to_map =
- files_to_register->GetMappingWithIDAdjustment(
- base::GlobalDescriptors::kBaseDescriptor);
-
-#if !defined(OS_MACOSX)
- if (process_type == switches::kRendererProcess) {
- const int sandbox_fd =
- RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
- fds_to_map.push_back(std::make_pair(
- sandbox_fd,
- GetSandboxFD()));
- }
-#endif // defined(OS_MACOSX)
-
- // Actually launch the app.
- base::LaunchOptions options;
- options.environ = env;
- options.fds_to_remap = &fds_to_map;
-
-#if defined(OS_MACOSX)
- // Hold the MachBroker lock for the duration of LaunchProcess. The child
- // will send its task port to the parent almost immediately after startup.
- // The Mach message will be delivered to the parent, but updating the
- // record of the launch will wait until after the placeholder PID is
- // inserted below. This ensures that while the child process may send its
- // port to the parent prior to the parent leaving LaunchProcess, the
- // order in which the record in MachBroker is updated is correct.
- MachBroker* broker = MachBroker::GetInstance();
- broker->GetLock().Acquire();
-
- // Make sure the MachBroker is running, and inform it to expect a
- // check-in from the new process.
- broker->EnsureRunning();
-
- const SandboxType sandbox_type = delegate->GetSandboxType();
- std::unique_ptr<sandbox::PreExecDelegate> pre_exec_delegate;
- if (BootstrapSandboxManager::ShouldEnable()) {
- BootstrapSandboxManager* sandbox_manager =
- BootstrapSandboxManager::GetInstance();
- if (sandbox_manager->EnabledForSandbox(sandbox_type)) {
- pre_exec_delegate = sandbox_manager->sandbox()->NewClient(sandbox_type);
- }
- }
- options.pre_exec_delegate = pre_exec_delegate.get();
-#endif // defined(OS_MACOSX)
-
- process = base::LaunchProcess(*cmd_line, options);
-
-#if defined(OS_MACOSX)
- if (process.IsValid()) {
- broker->AddPlaceholderForPid(process.Pid(), child_process_id);
- } else {
- if (pre_exec_delegate) {
- BootstrapSandboxManager::GetInstance()->sandbox()->RevokeToken(
- pre_exec_delegate->sandbox_token());
- }
- }
-
- // After updating the broker, release the lock and let the child's
- // message be processed on the broker's thread.
- broker->GetLock().Release();
-#endif // defined(OS_MACOSX)
- }
-#endif // else defined(OS_POSIX)
-#if !defined(OS_ANDROID)
- if (process.IsValid()) {
- launch_result = LAUNCH_RESULT_SUCCESS;
- RecordHistogramsOnLauncherThread(base::TimeTicks::Now() -
- begin_launch_time);
- }
- BrowserThread::PostTask(client_thread_id, FROM_HERE,
- base::Bind(callback, zygote, base::Passed(&process),
- launch_result));
-#endif // !defined(OS_ANDROID)
-}
-
-void TerminateOnLauncherThread(ZygoteHandle zygote, base::Process process) {
- DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
-#if defined(OS_ANDROID)
- VLOG(1) << "ChromeProcess: Stopping process with handle "
- << process.Handle();
- StopChildProcess(process.Handle());
-#else
- // Client has gone away, so just kill the process. Using exit code 0
- // means that UMA won't treat this as a crash.
- process.Terminate(RESULT_CODE_NORMAL_EXIT, false);
- // On POSIX, we must additionally reap the child.
-#if defined(OS_POSIX)
-#if !defined(OS_MACOSX)
- if (zygote) {
- // If the renderer was created via a zygote, we have to proxy the reaping
- // through the zygote process.
- zygote->EnsureProcessTerminated(process.Handle());
- } else
-#endif // !OS_MACOSX
- base::EnsureProcessTerminated(std::move(process));
-#endif // OS_POSIX
-#endif // defined(OS_ANDROID)
-}
-
-void SetProcessBackgroundedOnLauncherThread(base::Process process,
- bool background) {
- DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
- if (process.CanBackgroundProcesses()) {
-#if defined(OS_MACOSX)
- process.SetProcessBackgrounded(MachBroker::GetInstance(), background);
-#else
- process.SetProcessBackgrounded(background);
-#endif // defined(OS_MACOSX)
- }
-#if defined(OS_ANDROID)
- SetChildProcessInForeground(process.Handle(), !background);
-#endif
-}
-
} // namespace
ChildProcessLauncher::ChildProcessLauncher(
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
- std::unique_ptr<base::CommandLine> cmd_line,
+ std::unique_ptr<base::CommandLine> command_line,
int child_process_id,
Client* client,
const std::string& mojo_child_token,
@@ -406,95 +61,118 @@ ChildProcessLauncher::ChildProcessLauncher(
weak_factory_(this) {
DCHECK(CalledOnValidThread());
CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_));
- Launch(std::move(delegate), std::move(cmd_line), child_process_id);
+
+ helper_ = new Helper(child_process_id, client_thread_id_,
+ std::move(command_line), std::move(delegate),
+ weak_factory_.GetWeakPtr(), terminate_on_shutdown);
+ helper_->LaunchOnClientThread();
}
ChildProcessLauncher::~ChildProcessLauncher() {
DCHECK(CalledOnValidThread());
- if (process_.IsValid() && terminate_child_on_shutdown_) {
- // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So
- // don't this on the UI/IO threads.
- BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
- base::Bind(&TerminateOnLauncherThread, zygote_,
- base::Passed(&process_)));
- }
+ if (process_.IsValid() && terminate_child_on_shutdown_)
+ Terminate(zygote_, std::move(process_));
}
-void ChildProcessLauncher::Launch(
+ChildProcessLauncher::Helper::Helper(
boliu 2017/01/12 02:00:07 nit: group ChildProcessLauncher methods together a
Jay Civelli 2017/01/12 23:05:40 Done (they were defined in the order they were dec
+ int child_process_id,
+ BrowserThread::ID client_thread_id,
+ std::unique_ptr<base::CommandLine> command_line,
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
- std::unique_ptr<base::CommandLine> cmd_line,
- int child_process_id) {
- DCHECK(CalledOnValidThread());
+ const base::WeakPtr<ChildProcessLauncher>& child_process_launcher,
+ bool terminate_on_shutdown)
+ : child_process_id_(child_process_id),
+ client_thread_id_(client_thread_id),
+ command_line_(std::move(command_line)),
+ delegate_(std::move(delegate)),
+ child_process_launcher_(child_process_launcher),
+ terminate_on_shutdown_(terminate_on_shutdown) {
+}
-#if defined(OS_ANDROID)
- // Android only supports renderer, sandboxed utility and gpu.
- std::string process_type =
- cmd_line->GetSwitchValueASCII(switches::kProcessType);
- CHECK(process_type == switches::kGpuProcess ||
- process_type == switches::kRendererProcess ||
-#if BUILDFLAG(ENABLE_PLUGINS)
- process_type == switches::kPpapiPluginProcess ||
-#endif
- process_type == switches::kUtilityProcess)
- << "Unsupported process type: " << process_type;
+ChildProcessLauncher::Helper::~Helper() {}
- // Non-sandboxed utility or renderer process are currently not supported.
- DCHECK(process_type == switches::kGpuProcess ||
- !cmd_line->HasSwitch(switches::kNoSandbox));
+void ChildProcessLauncher::Helper::LaunchOnClientThread() {
+ DCHECK_CURRENTLY_ON(client_thread_id_);
-#endif
- mojo::edk::ScopedPlatformHandle server_handle;
- mojo::edk::ScopedPlatformHandle client_handle;
-#if defined(OS_WIN)
- if (delegate->ShouldLaunchElevated()) {
- mojo::edk::NamedPlatformChannelPair named_pair;
- server_handle = named_pair.PassServerHandle();
- named_pair.PrepareToPassClientHandleToChildProcess(cmd_line.get());
- } else
-#endif
- {
+ BeforeLaunchOnClientThread();
+
+ mojo_server_handle_ = PrepareMojoPipeHandlesOnClientThread();
+ if (!mojo_server_handle_.is_valid()) {
mojo::edk::PlatformChannelPair channel_pair;
- server_handle = channel_pair.PassServerHandle();
- client_handle = channel_pair.PassClientHandle();
+ mojo_server_handle_ = channel_pair.PassServerHandle();
+ mojo_client_handle_ = channel_pair.PassClientHandle();
}
- NotifyCallback reply_callback(base::Bind(&ChildProcessLauncher::DidLaunch,
- weak_factory_.GetWeakPtr(),
- terminate_child_on_shutdown_,
- base::Passed(&server_handle)));
+
BrowserThread::PostTask(
BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
- base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_,
- child_process_id, base::Passed(&delegate),
- base::Passed(&client_handle), base::Passed(&cmd_line)));
+ base::Bind(&Helper::LaunchOnLauncherThread, this));
}
-void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) {
- DCHECK(CalledOnValidThread());
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
- if (zygote_) {
- termination_status_ = zygote_->GetTerminationStatus(
- process_.Handle(), known_dead, &exit_code_);
- } else if (known_dead) {
- termination_status_ =
- base::GetKnownDeadTerminationStatus(process_.Handle(), &exit_code_);
- } else {
-#elif defined(OS_MACOSX)
- if (known_dead) {
- termination_status_ =
- base::GetKnownDeadTerminationStatus(process_.Handle(), &exit_code_);
- } else {
-#elif defined(OS_ANDROID)
- if (IsChildProcessOomProtected(process_.Handle())) {
- termination_status_ = base::TERMINATION_STATUS_OOM_PROTECTED;
+void ChildProcessLauncher::Helper::LaunchOnLauncherThread() {
+ DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
+
+ begin_launch_time_ = base::TimeTicks::Now();
+
+ std::unique_ptr<FileMappedForLaunch> files_to_register = GetFilesToMap();
+
+ base::Process process;
+ ZygoteHandle zygote = nullptr;
+ bool is_synchronous_launch = true;
+ int launch_result = LAUNCH_RESULT_FAILURE;
+ if (ShouldForkAsZygote()) {
+ zygote = ForkAsZygote(std::move(files_to_register), &process);
+ launch_result = LAUNCH_RESULT_SUCCESS;
} else {
-#else
- {
-#endif
- termination_status_ =
- base::GetTerminationStatus(process_.Handle(), &exit_code_);
+ base::LaunchOptions options;
+ BeforeLaunchOnLauncherThread(*files_to_register, &options);
+
+ process = LaunchProcessOnLauncherThread(options,
+ files_to_register.get(),
+ &is_synchronous_launch,
+ &launch_result);
+
+ AfterLaunchOnLauncherThread(process, options);
+ }
+
+ if (is_synchronous_launch) {
+ PostLaunchOnLauncherThread(std::move(process), zygote, launch_result);
}
}
+void ChildProcessLauncher::Helper::PostLaunchOnLauncherThread(
+ base::Process process,
+ ZygoteHandle zygote,
+ int launch_result) {
+ // Release the client handle now that the process has been started (the pipe
+ // may not signal when the process dies otherwise and we would not detect the
+ // child process died).
+ mojo_client_handle_.reset();
+
+ if (process.IsValid()) {
boliu 2017/01/12 02:00:07 on android, old code didn't check this to record h
Jay Civelli 2017/01/12 23:05:40 Yes, and that seemed wrong (the other platforms be
+ RecordHistogramsOnLauncherThread(
+ base::TimeTicks::Now() - begin_launch_time_);
+ }
+
+ BrowserThread::PostTask(
+ client_thread_id_, FROM_HERE,
+ base::Bind(&Helper::PostLaunchOnClientThread,
+ this, base::Passed(&process), zygote, launch_result));
+}
+
+void ChildProcessLauncher::Helper::PostLaunchOnClientThread(
+ base::Process process, ZygoteHandle zygote, int error_code) {
+ if (child_process_launcher_) {
+ child_process_launcher_->Notify(zygote, std::move(mojo_server_handle_),
+ std::move(process), error_code);
+ } else if (process.IsValid() && terminate_on_shutdown_) {
+ ChildProcessLauncher::Terminate(zygote, std::move(process));
+ }
+}
+
+std::string ChildProcessLauncher::Helper::GetProcessType() {
+ return command_line()->GetSwitchValueASCII(switches::kProcessType);
+}
+
void ChildProcessLauncher::SetProcessBackgrounded(bool background) {
DCHECK(CalledOnValidThread());
base::Process to_pass = process_.Duplicate();
@@ -503,33 +181,6 @@ void ChildProcessLauncher::SetProcessBackgrounded(bool background) {
base::Passed(&to_pass), background));
}
-void ChildProcessLauncher::DidLaunch(
- base::WeakPtr<ChildProcessLauncher> instance,
- bool terminate_on_shutdown,
- mojo::edk::ScopedPlatformHandle server_handle,
- ZygoteHandle zygote,
-#if defined(OS_ANDROID)
- base::ScopedFD mojo_fd,
-#endif
- base::Process process,
- int error_code) {
- if (!process.IsValid())
- LOG(ERROR) << "Failed to launch child process";
-
- if (instance.get()) {
- instance->Notify(zygote, std::move(server_handle),
- std::move(process), error_code);
- } else {
- if (process.IsValid() && terminate_on_shutdown) {
- // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So
- // don't this on the UI/IO threads.
- BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
- base::Bind(&TerminateOnLauncherThread, zygote,
- base::Passed(&process)));
- }
- }
-}
-
void ChildProcessLauncher::Notify(ZygoteHandle zygote,
mojo::edk::ScopedPlatformHandle server_handle,
base::Process process,
@@ -544,9 +195,7 @@ void ChildProcessLauncher::Notify(ZygoteHandle zygote,
mojo_child_token_, process_error_callback_);
}
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
zygote_ = zygote;
-#endif
if (process_.IsValid()) {
client_->OnProcessLaunched();
} else {
@@ -564,7 +213,7 @@ bool ChildProcessLauncher::IsStarting() {
const base::Process& ChildProcessLauncher::GetProcess() const {
// TODO(crbug.com/469248): This fails in some tests.
- // DCHECK(CalledOnValidThread());
+ // DCHECK(CalledOnValidThread());
return process_;
}
@@ -583,18 +232,22 @@ base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
if (exit_code)
*exit_code = exit_code_;
- // POSIX: If the process crashed, then the kernel closed the socket
- // for it and so the child has already died by the time we get
- // here. Since GetTerminationStatus called waitpid with WNOHANG,
- // it'll reap the process. However, if GetTerminationStatus didn't
- // reap the child (because it was still running), we'll need to
- // Terminate via ProcessWatcher. So we can't close the handle here.
+ // POSIX: If the process crashed, then the kernel closed the socket for it and
+ // so the child has already died by the time we get here. Since
+ // GetTerminationStatus called waitpid with WNOHANG, it'll reap the process.
+ // However, if GetTerminationStatus didn't reap the child (because it was
+ // still running), we'll need to Terminate via ProcessWatcher. So we can't
+ // close the handle here.
if (termination_status_ != base::TERMINATION_STATUS_STILL_RUNNING)
process_.Close();
return termination_status_;
}
+bool ChildProcessLauncher::Terminate(int exit_code, bool wait) {
+ return IsStarting() ? false : TerminateProcess(GetProcess(), exit_code, wait);
+}
+
ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
Client* client) {
Client* ret = client_;
@@ -602,4 +255,20 @@ ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
return ret;
}
+// static
+void ChildProcessLauncher::Terminate(
+ ZygoteHandle zygote, base::Process process) {
+ if (BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER)) {
+ ChildProcessLauncher::TerminateOnLauncherThread(zygote, std::move(process));
+ return;
+ }
+ // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So don't
+ // this on the UI/IO threads.
+ BrowserThread::PostTask(
+ BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
+ base::Bind(&ChildProcessLauncher::TerminateOnLauncherThread,
+ zygote, base::Passed(&process)));
+}
+
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698