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

Unified Diff: base/mp/mp_child_process_launcher.cc

Issue 1625015: Refactor ChildProcess and related classes to create a framework outside of br... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 10 years, 8 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
« no previous file with comments | « base/mp/mp_child_process_launcher.h ('k') | base/mp/mp_child_thread.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/mp/mp_child_process_launcher.cc
===================================================================
--- base/mp/mp_child_process_launcher.cc (revision 0)
+++ base/mp/mp_child_process_launcher.cc (revision 0)
@@ -0,0 +1,233 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/mp/mp_child_process_launcher.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/thread.h"
+
+#if defined(OS_POSIX)
+#include "base/global_descriptors_posix.h"
+#endif
+
+namespace base {
+
+// Having the functionality of MpChildProcessLauncher be in an internal
+// ref counted object allows us to automatically terminate the process when the
+// parent class destructs, while still holding on to state that we need.
+class MpChildProcessLauncher::Context
+ : public base::RefCountedThreadSafe<MpChildProcessLauncher::Context> {
+ public:
+ Context(MpChildProcessContext* process_context)
+ : process_context_(process_context),
+ starting_(true)
+#if defined(OS_LINUX)
+ , zygote_(false)
+#endif
+ {
+ }
+
+ void Launch(
+#if defined(OS_WIN)
+ const FilePath& exposed_dir,
+#elif defined(OS_POSIX)
+ bool use_zygote,
+ const base::environment_vector& environ,
+ int ipcfd,
+#endif
+ CommandLine* cmd_line,
+ Client* client) {
+ client_ = client;
+
+ CHECK(process_context_->GetCurrentThreadIdentifier(&client_thread_id_));
+
+ process_context_->PostProcessLauncherTask(
+ FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &Context::LaunchInternal,
+#if defined(OS_WIN)
+ exposed_dir,
+#elif defined(POSIX)
+ use_zygote,
+ environ,
+ ipcfd,
+#endif
+ cmd_line));
+ }
+
+ void ResetClient() {
+ // No need for locking as this function gets called on the same thread that
+ // client_ would be used.
+ CHECK(process_context_->CurrentlyOnThread(client_thread_id_));
+ client_ = NULL;
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<MpChildProcessLauncher::Context>;
+ friend class MpChildProcessLauncher;
+
+ ~Context() {
+ Terminate();
+ }
+
+ void LaunchInternal(
+#if defined(OS_WIN)
+ const FilePath& exposed_dir,
+#elif defined(OS_POSIX)
+ bool use_zygote,
+ const base::environment_vector& env,
+ int ipcfd,
+#endif
+ CommandLine* cmd_line) {
+ scoped_ptr<CommandLine> cmd_line_deleter(cmd_line);
+ base::ProcessHandle handle = process_context_->StartProcess(
+#if defined(OS_WIN)
+ exposed_dir,
+#elif defined(OS_POSIX)
+ use_zygote,
+ cenv,
+ ipcfd,
+#endif
+ cmd_line);
+
+ process_context_->PostTask(
+ client_thread_id_,
+ FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &MpChildProcessLauncher::Context::Notify,
+#if defined(OS_LINUX)
+ use_zygote,
+#endif
+ handle));
+ }
+
+ void Notify(
+#if defined(OS_LINUX)
+ bool zygote,
+#endif
+ base::ProcessHandle handle) {
+ starting_ = false;
+ process_.set_handle(handle);
+#if defined(OS_LINUX)
+ zygote_ = zygote;
+#endif
+ if (client_) {
+ client_->OnProcessLaunched();
+ } else {
+ Terminate();
+ }
+ }
+
+ void Terminate() {
+ if (!process_.handle())
+ return;
+
+ // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So
+ // don't this on the UI/IO threads.
+ process_context_->PostProcessLauncherTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &MpChildProcessLauncher::Context::TerminateInternal,
+#if defined(OS_LINUX)
+ zygote_,
+#endif
+ process_context_,
+ process_.handle()));
+ process_.set_handle(base::kNullProcessHandle);
+ }
+
+ static void TerminateInternal(
+#if defined(OS_LINUX)
+ bool zygote,
+#endif
+ MpChildProcessContext* process_context,
+ base::ProcessHandle handle) {
+ base::Process process(handle);
+ // 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(process_context->GetNormalExitResultCode());
+ process_context->EnsureProcessTerminated(handle);
+ process.Close();
+ }
+
+ MpChildProcessContext* process_context_;
+ Client* client_;
+ int client_thread_id_;
+ base::Process process_;
+ bool starting_;
+
+#if defined(OS_LINUX)
+ bool zygote_;
+#endif
+};
+
+
+MpChildProcessLauncher::MpChildProcessLauncher(
+#if defined(OS_WIN)
+ const FilePath& exposed_dir,
+#elif defined(OS_POSIX)
+ bool use_zygote,
+ const base::environment_vector& environ,
+ int ipcfd,
+#endif
+ CommandLine* cmd_line,
+ MpChildProcessContext* context,
+ Client* client) : process_context_(context) {
+ context_ = new Context(process_context_);
+ context_->Launch(
+#if defined(OS_WIN)
+ exposed_dir,
+#elif defined(OS_POSIX)
+ use_zygote,
+ environ,
+ ipcfd,
+#endif
+ cmd_line,
+ client);
+}
+
+MpChildProcessLauncher::~MpChildProcessLauncher() {
+ context_->ResetClient();
+}
+
+bool MpChildProcessLauncher::IsStarting() {
+ return context_->starting_;
+}
+
+base::ProcessHandle MpChildProcessLauncher::GetHandle() {
+ DCHECK(!context_->starting_);
+ return context_->process_.handle();
+}
+
+bool MpChildProcessLauncher::DidProcessCrash() {
+ bool did_crash, child_exited;
+ base::ProcessHandle handle = context_->process_.handle();
+ did_crash = process_context_->CheckProcessCrash(
+ &child_exited,
+#if defined(OS_POSIX)
+ context_->zygote_,
+#endif
+ handle);
+
+ // 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
+ // DidProcessCrash called waitpid with WNOHANG, it'll reap the process.
+ // However, if DidProcessCrash didn't reap the child, we'll need to in
+ // Terminate via ProcessWatcher. So we can't close the handle here.
+ if (child_exited)
+ context_->process_.Close();
+
+ return did_crash;
+}
+
+void MpChildProcessLauncher::SetProcessBackgrounded(bool background) {
+ DCHECK(!context_->starting_);
+ context_->process_.SetProcessBackgrounded(background);
+}
+
+} // namespace base
« no previous file with comments | « base/mp/mp_child_process_launcher.h ('k') | base/mp/mp_child_thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698