child_process_launcher.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/child_process_launcher.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>  // For std::pair.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
1558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/content_browser_client.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_descriptors.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/result_codes.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/sandbox_win.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/sandbox_init.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/sandboxed_process_launcher_delegate.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/mach_broker_mac.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/jni_android.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/android/child_process_launcher_android.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/memory/shared_memory.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_sandbox_host_linux.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/zygote_host/zygote_host_impl_linux.h"
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/common/child_process_sandbox_support_impl_linux.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/metrics/stats_table.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/posix/global_descriptors.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Having the functionality of ChildProcessLauncher be in an internal
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ref counted object allows us to automatically terminate the process when the
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parent class destructs, while still holding on to state that we need.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChildProcessLauncher::Context
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCountedThreadSafe<ChildProcessLauncher::Context> {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Context()
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : client_(NULL),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        client_thread_id_(BrowserThread::UI),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exit_code_(RESULT_CODE_NORMAL_EXIT),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        starting_(true)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        , zygote_(false)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()->
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              HasSwitch(switches::kChildCleanExit);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          terminate_child_on_shutdown_ = true;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Launch(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SandboxedProcessLauncherDelegate* delegate,
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool launch_elevated,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int ipcfd,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool use_zygote,
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const base::EnvironmentMap& environ,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int ipcfd,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CommandLine* cmd_line,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int child_process_id,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Client* client) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_ = client;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to close the client end of the IPC channel to reliably detect
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // child termination. We will close this fd after we create the child
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // process which is asynchronous on Android.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipcfd_ = ipcfd;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            &Context::LaunchInternal,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            make_scoped_refptr(this),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            client_thread_id_,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            child_process_id,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            delegate,
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            launch_elevated,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ipcfd,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            use_zygote,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            environ,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ipcfd,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            cmd_line));
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void OnChildProcessStarted(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |this_object| is NOT thread safe. Only use it to post a task back.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<Context> this_object,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::ID client_thread_id,
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::TimeTicks begin_launch_time,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ProcessHandle handle) {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RecordHistograms(begin_launch_time);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (BrowserThread::CurrentlyOn(client_thread_id)) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is always invoked on the UI thread which is commonly the
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |client_thread_id| so we can shortcut one PostTask.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this_object->Notify(handle);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::PostTask(
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          client_thread_id, FROM_HERE,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &ChildProcessLauncher::Context::Notify,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              this_object,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              handle));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetClient() {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No need for locking as this function gets called on the same thread that
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // client_ would be used.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(BrowserThread::CurrentlyOn(client_thread_id_));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_ = NULL;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_terminate_child_on_shutdown(bool terminate_on_shutdown) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    terminate_child_on_shutdown_ = terminate_on_shutdown;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class ChildProcessLauncher;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Context() {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Terminate();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void RecordHistograms(const base::TimeTicks begin_launch_time) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER)) {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RecordLaunchHistograms(launch_time);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::PostTask(
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&ChildProcessLauncher::Context::RecordLaunchHistograms,
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     launch_time));
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void RecordLaunchHistograms(const base::TimeDelta launch_time) {
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Log the launch time, separating out the first one (which will likely be
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // slower due to the rest of the browser initializing at the same time).
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static bool done_first_launch = false;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (done_first_launch) {
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time);
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchFirst", launch_time);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      done_first_launch = true;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void LaunchInternal(
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |this_object| is NOT thread safe. Only use it to post a task back.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<Context> this_object,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::ID client_thread_id,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int child_process_id,
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SandboxedProcessLauncherDelegate* delegate,
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool launch_elevated,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int ipcfd,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool use_zygote,
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const base::EnvironmentMap& env,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int ipcfd,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CommandLine* cmd_line) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<CommandLine> cmd_line_deleter(cmd_line);
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeTicks begin_launch_time = base::TimeTicks::Now();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ProcessHandle handle = base::kNullProcessHandle;
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (launch_elevated) {
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::LaunchOptions options;
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      options.start_hidden = true;
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::LaunchElevatedProcess(*cmd_line, options, &handle);
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      handle = StartSandboxedProcess(delegate, cmd_line);
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#elif defined(OS_POSIX)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string process_type =
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cmd_line->GetSwitchValueASCII(switches::kProcessType);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<FileDescriptorInfo> files_to_register;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    files_to_register.push_back(
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileDescriptorInfo(kPrimaryIPCChannel,
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           base::FileDescriptor(ipcfd, false)));
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::StatsTable* stats_table = base::StatsTable::current();
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (stats_table &&
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::SharedMemory::IsHandleValid(
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            stats_table->GetSharedMemoryHandle())) {
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      files_to_register.push_back(
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          FileDescriptorInfo(kStatsTableSharedMemFd,
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             stats_table->GetSharedMemoryHandle()));
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if defined(OS_ANDROID)
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Android WebView runs in single process, ensure that we never get here
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // when running in single process mode.
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetContentClient()->browser()->
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                &files_to_register);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StartChildProcess(cmd_line->argv(), files_to_register,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&ChildProcessLauncher::Context::OnChildProcessStarted,
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   this_object, client_thread_id, begin_launch_time));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ProcessHandle handle = base::kNullProcessHandle;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to close the client end of the IPC channel to reliably detect
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // child termination.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_util::ScopedFD ipcfd_closer(&ipcfd);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetContentClient()->browser()->
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                &files_to_register);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_zygote) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(),
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          files_to_register,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          process_type);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Fall through to the normal posix case below when we're not zygoting.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Convert FD mapping to FileHandleMappingVector
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::FileHandleMappingVector fds_to_map;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < files_to_register.size(); ++i) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fds_to_map.push_back(std::make_pair(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            files_to_register[i].fd.fd,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            files_to_register[i].id +
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                base::GlobalDescriptors::kBaseDescriptor));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (process_type == switches::kRendererProcess) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const int sandbox_fd =
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fds_to_map.push_back(std::make_pair(
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sandbox_fd,
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            GetSandboxFD()));
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Actually launch the app.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::LaunchOptions options;
28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      options.environ = env;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      options.fds_to_remap = &fds_to_map;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Hold the MachBroker lock for the duration of LaunchProcess. The child
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // will send its task port to the parent almost immediately after startup.
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // The Mach message will be delivered to the parent, but updating the
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // record of the launch will wait until after the placeholder PID is
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // inserted below. This ensures that while the child process may send its
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // port to the parent prior to the parent leaving LaunchProcess, the
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // order in which the record in MachBroker is updated is correct.
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      MachBroker* broker = MachBroker::GetInstance();
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      broker->GetLock().Acquire();
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Make sure the MachBroker is running, and inform it to expect a
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // check-in from the new process.
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      broker->EnsureRunning();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool launched = base::LaunchProcess(*cmd_line, options, &handle);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (launched)
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        broker->AddPlaceholderForPid(handle);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // After updating the broker, release the lock and let the child's
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // messasge be processed on the broker's thread.
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      broker->GetLock().Release();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!launched)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handle = base::kNullProcessHandle;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // else defined(OS_POSIX)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (handle)
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RecordHistograms(begin_launch_time);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_thread_id, FROM_HERE,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &Context::Notify,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this_object.get(),
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          use_zygote,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          handle));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_ANDROID)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Notify(
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool zygote,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ProcessHandle handle) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Finally close the ipcfd
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_util::ScopedFD ipcfd_closer(&ipcfd_);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    starting_ = false;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process_.set_handle(handle);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!handle)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to launch child process";
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zygote_ = zygote;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (client_) {
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (handle) {
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        client_->OnProcessLaunched();
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        client_->OnProcessLaunchFailed();
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Terminate();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Terminate() {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!process_.handle())
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!terminate_child_on_shutdown_)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep!  So
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // don't this on the UI/IO threads.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            &Context::TerminateInternal,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            zygote_,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            process_.handle()));
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process_.set_handle(base::kNullProcessHandle);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void SetProcessBackgrounded(base::ProcessHandle handle,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     bool background) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Process process(handle);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process.SetProcessBackgrounded(background);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void TerminateInternal(
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool zygote,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ProcessHandle handle) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(0) << "ChromeProcess: Stopping process with handle " << handle;
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StopChildProcess(handle);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Process process(handle);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     // Client has gone away, so just kill the process.  Using exit code 0
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // means that UMA won't treat this as a crash.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process.Terminate(RESULT_CODE_NORMAL_EXIT);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On POSIX, we must additionally reap the child.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (zygote) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If the renderer was created via a zygote, we have to proxy the reaping
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // through the zygote process.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(handle);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !OS_MACOSX
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::EnsureProcessTerminated(handle);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_POSIX
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process.Close();
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_ANDROID)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Client* client_;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::ID client_thread_id_;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Process process_;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TerminationStatus termination_status_;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int exit_code_;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool starting_;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Controls whether the child process should be terminated on browser
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shutdown. Default behavior is to terminate the child.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool terminate_child_on_shutdown_;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The fd to close after creating the process.
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ipcfd_;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) && !defined(OS_MACOSX)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool zygote_;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChildProcessLauncher::ChildProcessLauncher(
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SandboxedProcessLauncherDelegate* delegate,
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool launch_elevated,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool use_zygote,
43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const base::EnvironmentMap& environ,
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ipcfd,
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine* cmd_line,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int child_process_id,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Client* client) {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_ = new Context();
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_->Launch(
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delegate,
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      launch_elevated,
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ipcfd,
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_zygote,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      environ,
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ipcfd,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmd_line,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      child_process_id,
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChildProcessLauncher::~ChildProcessLauncher() {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_->ResetClient();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChildProcessLauncher::IsStarting() {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context_->starting_;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle ChildProcessLauncher::GetHandle() {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!context_->starting_);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context_->process_.handle();
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool known_dead,
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* exit_code) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ProcessHandle handle = context_->process_.handle();
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (handle == base::kNullProcessHandle) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Process is already gone, so return the cached termination status.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (exit_code)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *exit_code = context_->exit_code_;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return context_->termination_status_;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context_->zygote_) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_->termination_status_ = ZygoteHostImpl::GetInstance()->
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetTerminationStatus(handle, known_dead, &context_->exit_code_);
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (known_dead) {
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    context_->termination_status_ =
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
492d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#elif defined(OS_MACOSX)
493d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (known_dead) {
494d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    context_->termination_status_ =
495d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#elif defined(OS_ANDROID)
498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (IsChildProcessOomProtected(handle)) {
499f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      context_->termination_status_ = base::TERMINATION_STATUS_OOM_PROTECTED;
500f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
501f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#else
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_->termination_status_ =
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::GetTerminationStatus(handle, &context_->exit_code_);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exit_code)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *exit_code = context_->exit_code_;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // POSIX: If the process crashed, then the kernel closed the socket
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for it and so the child has already died by the time we get
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here. Since GetTerminationStatus called waitpid with WNOHANG,
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it'll reap the process.  However, if GetTerminationStatus didn't
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reap the child (because it was still running), we'll need to
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Terminate via ProcessWatcher. So we can't close the handle here.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context_->termination_status_ != base::TERMINATION_STATUS_STILL_RUNNING)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_->process_.Close();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context_->termination_status_;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcessLauncher::SetProcessBackgrounded(bool background) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &ChildProcessLauncher::Context::SetProcessBackgrounded,
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetHandle(), background));
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcessLauncher::SetTerminateChildOnShutdown(
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool terminate_on_shutdown) {
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (context_.get())
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_->set_terminate_child_on_shutdown(terminate_on_shutdown);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
538