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