blob: bee658d187329d570f2a3a6be1830ece92e5677c [file] [log] [blame]
[email protected]ffb69732012-02-08 17:33:231// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]9610ef242009-11-18 02:41:262// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]df8e899b2011-02-22 22:58:225#include "content/browser/child_process_launcher.h"
[email protected]9610ef242009-11-18 02:41:266
[email protected]eb1bd832010-05-18 20:39:587#include <utility> // For std::pair.
8
[email protected]037edb52011-11-15 21:14:069#include "base/bind.h"
[email protected]9610ef242009-11-18 02:41:2610#include "base/command_line.h"
[email protected]2ce26c432011-09-19 17:08:1211#include "base/file_util.h"
[email protected]9610ef242009-11-18 02:41:2612#include "base/logging.h"
[email protected]3b63f8f42011-03-28 01:54:1513#include "base/memory/scoped_ptr.h"
[email protected]eaac71592011-11-23 18:32:0014#include "base/process_util.h"
[email protected]20305ec2011-01-21 04:55:5215#include "base/synchronization/lock.h"
[email protected]34b99632011-01-01 01:01:0616#include "base/threading/thread.h"
[email protected]c38831a12011-10-28 12:44:4917#include "content/public/browser/browser_thread.h"
[email protected]87f3c082011-10-19 18:07:4418#include "content/public/browser/content_browser_client.h"
[email protected]b3aabd342012-06-04 19:33:5619#include "content/public/common/content_descriptors.h"
[email protected]c08950d22011-10-13 22:20:2920#include "content/public/common/content_switches.h"
[email protected]b39ef1cb2011-10-25 04:46:5521#include "content/public/common/result_codes.h"
[email protected]9610ef242009-11-18 02:41:2622
23#if defined(OS_WIN)
[email protected]864b1362010-08-19 03:49:3824#include "base/file_path.h"
[email protected]cd5fa1a2011-05-28 18:21:4725#include "content/common/sandbox_policy.h"
[email protected]e25b04c92012-10-23 20:05:0626#include "content/public/common/sandbox_init.h"
[email protected]e63c4d72011-05-31 22:38:2927#elif defined(OS_MACOSX)
[email protected]ed0fbe62011-06-23 18:32:1128#include "content/browser/mach_broker_mac.h"
[email protected]30935362012-06-28 21:26:2329#elif defined(OS_ANDROID)
30#include "base/android/jni_android.h"
31#include "content/browser/android/sandboxed_process_launcher.h"
[email protected]e63c4d72011-05-31 22:38:2932#elif defined(OS_POSIX)
[email protected]3b63f8f42011-03-28 01:54:1533#include "base/memory/singleton.h"
[email protected]a01efd22011-03-01 00:38:3234#include "content/browser/renderer_host/render_sandbox_host_linux.h"
[email protected]13d6b3c2012-07-24 01:31:3135#include "content/browser/zygote_host/zygote_host_impl_linux.h"
[email protected]9610ef242009-11-18 02:41:2636#endif
37
[email protected]fb1277e82009-11-21 20:32:3038#if defined(OS_POSIX)
[email protected]613eef62012-11-09 23:46:5439#include "base/posix/global_descriptors.h"
[email protected]fb1277e82009-11-21 20:32:3040#endif
41
[email protected]130757672012-10-24 00:26:1942namespace content {
[email protected]631bb742011-11-02 11:29:3943
[email protected]9610ef242009-11-18 02:41:2644// Having the functionality of ChildProcessLauncher be in an internal
45// ref counted object allows us to automatically terminate the process when the
46// parent class destructs, while still holding on to state that we need.
47class ChildProcessLauncher::Context
48 : public base::RefCountedThreadSafe<ChildProcessLauncher::Context> {
49 public:
[email protected]fb1277e82009-11-21 20:32:3050 Context()
[email protected]18cbea32010-10-13 19:56:0051 : client_(NULL),
52 client_thread_id_(BrowserThread::UI),
[email protected]f3c1d3c2011-07-25 18:50:4853 termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
[email protected]130757672012-10-24 00:26:1954 exit_code_(RESULT_CODE_NORMAL_EXIT),
[email protected]08c426a2012-04-10 20:37:3355 starting_(true)
[email protected]ffb69732012-02-08 17:33:2356#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]fb1277e82009-11-21 20:32:3057 , zygote_(false)
58#endif
59 {
[email protected]08c426a2012-04-10 20:37:3360#if defined(OS_POSIX)
61 terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()->
[email protected]719a2052012-07-30 21:00:4362 HasSwitch(switches::kChildCleanExit);
[email protected]08c426a2012-04-10 20:37:3363#else
64 terminate_child_on_shutdown_ = true;
65#endif
[email protected]fb1277e82009-11-21 20:32:3066 }
[email protected]9610ef242009-11-18 02:41:2667
[email protected]fb1277e82009-11-21 20:32:3068 void Launch(
69#if defined(OS_WIN)
70 const FilePath& exposed_dir,
[email protected]30935362012-06-28 21:26:2371#elif defined(OS_ANDROID)
72 int ipcfd,
[email protected]fb1277e82009-11-21 20:32:3073#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:4274 bool use_zygote,
[email protected]a82af392012-02-24 04:40:2075 const base::EnvironmentVector& environ,
[email protected]fb1277e82009-11-21 20:32:3076 int ipcfd,
77#endif
78 CommandLine* cmd_line,
[email protected]40da3e0c2012-10-24 22:03:3879 int child_process_id,
[email protected]fb1277e82009-11-21 20:32:3080 Client* client) {
[email protected]9610ef242009-11-18 02:41:2681 client_ = client;
82
[email protected]d04e7662010-10-10 22:24:4883 CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_));
[email protected]9610ef242009-11-18 02:41:2684
[email protected]30935362012-06-28 21:26:2385#if defined(OS_ANDROID)
86 // We need to close the client end of the IPC channel to reliably detect
87 // child termination. We will close this fd after we create the child
88 // process which is asynchronous on Android.
89 ipcfd_ = ipcfd;
90#endif
[email protected]d04e7662010-10-10 22:24:4891 BrowserThread::PostTask(
92 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
[email protected]037edb52011-11-15 21:14:0693 base::Bind(
[email protected]fb1277e82009-11-21 20:32:3094 &Context::LaunchInternal,
[email protected]e2024782011-09-07 20:20:5195 make_scoped_refptr(this),
96 client_thread_id_,
[email protected]40da3e0c2012-10-24 22:03:3897 child_process_id,
[email protected]fb1277e82009-11-21 20:32:3098#if defined(OS_WIN)
99 exposed_dir,
[email protected]30935362012-06-28 21:26:23100#elif defined(OS_ANDROID)
101 ipcfd,
[email protected]eb1bd832010-05-18 20:39:58102#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:42103 use_zygote,
[email protected]3d2217d2009-11-23 21:26:47104 environ,
[email protected]fb1277e82009-11-21 20:32:30105 ipcfd,
106#endif
107 cmd_line));
[email protected]9610ef242009-11-18 02:41:26108 }
109
[email protected]30935362012-06-28 21:26:23110#if defined(OS_ANDROID)
111 static void OnSandboxedProcessStarted(
112 // |this_object| is NOT thread safe. Only use it to post a task back.
113 scoped_refptr<Context> this_object,
114 BrowserThread::ID client_thread_id,
115 base::ProcessHandle handle) {
116 if (BrowserThread::CurrentlyOn(client_thread_id)) {
117 // This is always invoked on the UI thread which is commonly the
118 // |client_thread_id| so we can shortcut one PostTask.
119 this_object->Notify(handle);
120 } else {
121 BrowserThread::PostTask(
122 client_thread_id, FROM_HERE,
123 base::Bind(
124 &ChildProcessLauncher::Context::Notify,
125 this_object,
126 handle));
127 }
128 }
129#endif
130
[email protected]9610ef242009-11-18 02:41:26131 void ResetClient() {
132 // No need for locking as this function gets called on the same thread that
133 // client_ would be used.
[email protected]d04e7662010-10-10 22:24:48134 CHECK(BrowserThread::CurrentlyOn(client_thread_id_));
[email protected]9610ef242009-11-18 02:41:26135 client_ = NULL;
136 }
137
[email protected]358cb8e2011-05-25 02:12:45138 void set_terminate_child_on_shutdown(bool terminate_on_shutdown) {
139 terminate_child_on_shutdown_ = terminate_on_shutdown;
140 }
141
[email protected]9610ef242009-11-18 02:41:26142 private:
143 friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>;
144 friend class ChildProcessLauncher;
145
146 ~Context() {
147 Terminate();
148 }
149
[email protected]e2024782011-09-07 20:20:51150 static void LaunchInternal(
151 // |this_object| is NOT thread safe. Only use it to post a task back.
152 scoped_refptr<Context> this_object,
153 BrowserThread::ID client_thread_id,
[email protected]40da3e0c2012-10-24 22:03:38154 int child_process_id,
[email protected]fb1277e82009-11-21 20:32:30155#if defined(OS_WIN)
156 const FilePath& exposed_dir,
[email protected]30935362012-06-28 21:26:23157#elif defined(OS_ANDROID)
158 int ipcfd,
[email protected]fb1277e82009-11-21 20:32:30159#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:42160 bool use_zygote,
[email protected]a82af392012-02-24 04:40:20161 const base::EnvironmentVector& env,
[email protected]fb1277e82009-11-21 20:32:30162 int ipcfd,
163#endif
164 CommandLine* cmd_line) {
[email protected]9610ef242009-11-18 02:41:26165 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line);
[email protected]2ce26c432011-09-19 17:08:12166
[email protected]9610ef242009-11-18 02:41:26167#if defined(OS_WIN)
[email protected]e25b04c92012-10-23 20:05:06168 base::ProcessHandle handle = content::StartProcessWithAccess(
[email protected]30935362012-06-28 21:26:23169 cmd_line, exposed_dir);
170#elif defined(OS_ANDROID)
171 std::string process_type =
172 cmd_line->GetSwitchValueASCII(switches::kProcessType);
[email protected]130757672012-10-24 00:26:19173 std::vector<FileDescriptorInfo> files_to_register;
[email protected]c7abd422012-09-25 00:20:08174 files_to_register.push_back(
[email protected]130757672012-10-24 00:26:19175 FileDescriptorInfo(kPrimaryIPCChannel,
[email protected]c7abd422012-09-25 00:20:08176 base::FileDescriptor(ipcfd, false)));
177
[email protected]130757672012-10-24 00:26:19178 GetContentClient()->browser()->
[email protected]40da3e0c2012-10-24 22:03:38179 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
180 &files_to_register);
[email protected]30935362012-06-28 21:26:23181
[email protected]130757672012-10-24 00:26:19182 StartSandboxedProcess(cmd_line->argv(), files_to_register,
[email protected]30935362012-06-28 21:26:23183 base::Bind(&ChildProcessLauncher::Context::OnSandboxedProcessStarted,
184 this_object, client_thread_id));
185
[email protected]9610ef242009-11-18 02:41:26186#elif defined(OS_POSIX)
[email protected]30935362012-06-28 21:26:23187 base::ProcessHandle handle = base::kNullProcessHandle;
[email protected]c7abd422012-09-25 00:20:08188 // We need to close the client end of the IPC channel to reliably detect
189 // child termination.
[email protected]2ce26c432011-09-19 17:08:12190 file_util::ScopedFD ipcfd_closer(&ipcfd);
[email protected]9610ef242009-11-18 02:41:26191
[email protected]54457f32011-04-15 22:05:29192 std::string process_type =
193 cmd_line->GetSwitchValueASCII(switches::kProcessType);
[email protected]130757672012-10-24 00:26:19194 std::vector<FileDescriptorInfo> files_to_register;
[email protected]c7abd422012-09-25 00:20:08195 files_to_register.push_back(
[email protected]130757672012-10-24 00:26:19196 FileDescriptorInfo(kPrimaryIPCChannel,
[email protected]c7abd422012-09-25 00:20:08197 base::FileDescriptor(ipcfd, false)));
198
[email protected]30935362012-06-28 21:26:23199#if !defined(OS_MACOSX)
[email protected]130757672012-10-24 00:26:19200 GetContentClient()->browser()->
[email protected]40da3e0c2012-10-24 22:03:38201 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
202 &files_to_register);
[email protected]7c4ea142010-01-26 05:15:42203 if (use_zygote) {
[email protected]c2c68b1f2012-02-25 00:29:15204 handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(),
[email protected]a1733df2012-06-22 11:24:18205 files_to_register,
[email protected]c2c68b1f2012-02-25 00:29:15206 process_type);
[email protected]7c4ea142010-01-26 05:15:42207 } else
208 // Fall through to the normal posix case below when we're not zygoting.
[email protected]30935362012-06-28 21:26:23209#endif // !defined(OS_MACOSX)
[email protected]fb1277e82009-11-21 20:32:30210 {
[email protected]a1733df2012-06-22 11:24:18211 // Convert FD mapping to FileHandleMappingVector
[email protected]a82af392012-02-24 04:40:20212 base::FileHandleMappingVector fds_to_map;
[email protected]40da3e0c2012-10-24 22:03:38213 for (size_t i = 0; i < files_to_register.size(); ++i) {
[email protected]54457f32011-04-15 22:05:29214 fds_to_map.push_back(std::make_pair(
[email protected]40da3e0c2012-10-24 22:03:38215 files_to_register[i].fd.fd,
216 files_to_register[i].id +
217 base::GlobalDescriptors::kBaseDescriptor));
[email protected]9610ef242009-11-18 02:41:26218 }
[email protected]a1733df2012-06-22 11:24:18219
[email protected]30935362012-06-28 21:26:23220#if !defined(OS_MACOSX)
[email protected]b80f68432011-05-02 17:22:30221 if (process_type == switches::kRendererProcess) {
[email protected]fb1277e82009-11-21 20:32:30222 const int sandbox_fd =
[email protected]d3c6c0d72010-12-09 08:15:04223 RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
[email protected]fb1277e82009-11-21 20:32:30224 fds_to_map.push_back(std::make_pair(
225 sandbox_fd,
226 kSandboxIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
227 }
[email protected]30935362012-06-28 21:26:23228#endif // defined(OS_MACOSX)
[email protected]9610ef242009-11-18 02:41:26229
[email protected]84b2d1d2011-09-01 21:44:24230 // Actually launch the app.
231 base::LaunchOptions options;
232 options.environ = &env;
233 options.fds_to_remap = &fds_to_map;
234
[email protected]c0028792010-01-12 00:39:15235#if defined(OS_MACOSX)
[email protected]84b2d1d2011-09-01 21:44:24236 // Use synchronization to make sure that the MachBroker is ready to
237 // receive a check-in from the new process before the new process
238 // actually tries to check in.
239 base::LaunchSynchronizationHandle synchronization_handle;
240 options.synchronize = &synchronization_handle;
241#endif // defined(OS_MACOSX)
242
243 bool launched = base::LaunchProcess(*cmd_line, options, &handle);
244
245#if defined(OS_MACOSX)
246 if (launched) {
[email protected]dc8caba2010-12-13 16:52:35247 MachBroker* broker = MachBroker::GetInstance();
[email protected]84b2d1d2011-09-01 21:44:24248 {
249 base::AutoLock lock(broker->GetLock());
[email protected]b88a7492010-09-17 12:28:32250
[email protected]84b2d1d2011-09-01 21:44:24251 // Make sure the MachBroker is running, and inform it to expect a
252 // check-in from the new process.
253 broker->EnsureRunning();
[email protected]b88a7492010-09-17 12:28:32254 broker->AddPlaceholderForPid(handle);
[email protected]84b2d1d2011-09-01 21:44:24255 }
256
257 // Now that the MachBroker is ready, the child may continue.
258 base::LaunchSynchronize(synchronization_handle);
259 }
260#endif // defined(OS_MACOSX)
261
[email protected]c0028792010-01-12 00:39:15262 if (!launched)
[email protected]9610ef242009-11-18 02:41:26263 handle = base::kNullProcessHandle;
264 }
[email protected]c0028792010-01-12 00:39:15265#endif // else defined(OS_POSIX)
[email protected]30935362012-06-28 21:26:23266#if !defined(OS_ANDROID)
267 BrowserThread::PostTask(
268 client_thread_id, FROM_HERE,
269 base::Bind(
270 &Context::Notify,
271 this_object.get(),
272#if defined(OS_POSIX) && !defined(OS_MACOSX)
273 use_zygote,
[email protected]fb1277e82009-11-21 20:32:30274#endif
[email protected]30935362012-06-28 21:26:23275 handle));
276#endif // !defined(OS_ANDROID)
[email protected]9610ef242009-11-18 02:41:26277 }
278
[email protected]cd69619b2010-05-05 02:41:38279 void Notify(
[email protected]ffb69732012-02-08 17:33:23280#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]fb1277e82009-11-21 20:32:30281 bool zygote,
282#endif
283 base::ProcessHandle handle) {
[email protected]30935362012-06-28 21:26:23284#if defined(OS_ANDROID)
285 // Finally close the ipcfd
286 file_util::ScopedFD ipcfd_closer(&ipcfd_);
287#endif
[email protected]9610ef242009-11-18 02:41:26288 starting_ = false;
289 process_.set_handle(handle);
[email protected]e51ddf252011-10-12 17:33:21290 if (!handle)
291 LOG(ERROR) << "Failed to launch child process";
292
[email protected]ffb69732012-02-08 17:33:23293#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]9610ef242009-11-18 02:41:26294 zygote_ = zygote;
[email protected]fb1277e82009-11-21 20:32:30295#endif
[email protected]9610ef242009-11-18 02:41:26296 if (client_) {
297 client_->OnProcessLaunched();
298 } else {
299 Terminate();
300 }
301 }
302
303 void Terminate() {
304 if (!process_.handle())
305 return;
306
[email protected]358cb8e2011-05-25 02:12:45307 if (!terminate_child_on_shutdown_)
308 return;
309
[email protected]9610ef242009-11-18 02:41:26310 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So
311 // don't this on the UI/IO threads.
[email protected]d04e7662010-10-10 22:24:48312 BrowserThread::PostTask(
313 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
[email protected]037edb52011-11-15 21:14:06314 base::Bind(
[email protected]e2024782011-09-07 20:20:51315 &Context::TerminateInternal,
[email protected]ffb69732012-02-08 17:33:23316#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]fb1277e82009-11-21 20:32:30317 zygote_,
318#endif
319 process_.handle()));
[email protected]9610ef242009-11-18 02:41:26320 process_.set_handle(base::kNullProcessHandle);
321 }
322
[email protected]e2024782011-09-07 20:20:51323 static void SetProcessBackgrounded(base::ProcessHandle handle,
324 bool background) {
325 base::Process process(handle);
326 process.SetProcessBackgrounded(background);
[email protected]3e55e212011-03-24 19:45:02327 }
328
[email protected]fb1277e82009-11-21 20:32:30329 static void TerminateInternal(
[email protected]ffb69732012-02-08 17:33:23330#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]fb1277e82009-11-21 20:32:30331 bool zygote,
332#endif
333 base::ProcessHandle handle) {
[email protected]30935362012-06-28 21:26:23334#if defined(OS_ANDROID)
335 LOG(INFO) << "ChromeProcess: Stopping process with handle " << handle;
[email protected]130757672012-10-24 00:26:19336 StopSandboxedProcess(handle);
[email protected]30935362012-06-28 21:26:23337#else
[email protected]9610ef242009-11-18 02:41:26338 base::Process process(handle);
339 // Client has gone away, so just kill the process. Using exit code 0
340 // means that UMA won't treat this as a crash.
[email protected]130757672012-10-24 00:26:19341 process.Terminate(RESULT_CODE_NORMAL_EXIT);
[email protected]9610ef242009-11-18 02:41:26342 // On POSIX, we must additionally reap the child.
343#if defined(OS_POSIX)
[email protected]30935362012-06-28 21:26:23344#if !defined(OS_MACOSX)
[email protected]fb1277e82009-11-21 20:32:30345 if (zygote) {
[email protected]9610ef242009-11-18 02:41:26346 // If the renderer was created via a zygote, we have to proxy the reaping
347 // through the zygote process.
[email protected]c2c68b1f2012-02-25 00:29:15348 ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(handle);
[email protected]fb1277e82009-11-21 20:32:30349 } else
[email protected]e63c4d72011-05-31 22:38:29350#endif // !OS_MACOSX
[email protected]fb1277e82009-11-21 20:32:30351 {
[email protected]eaac71592011-11-23 18:32:00352 base::EnsureProcessTerminated(handle);
[email protected]9610ef242009-11-18 02:41:26353 }
[email protected]e36e86f2009-12-15 11:55:08354#endif // OS_POSIX
[email protected]9610ef242009-11-18 02:41:26355 process.Close();
[email protected]30935362012-06-28 21:26:23356#endif // defined(OS_ANDROID)
[email protected]9610ef242009-11-18 02:41:26357 }
358
359 Client* client_;
[email protected]d04e7662010-10-10 22:24:48360 BrowserThread::ID client_thread_id_;
[email protected]9610ef242009-11-18 02:41:26361 base::Process process_;
[email protected]f3c1d3c2011-07-25 18:50:48362 base::TerminationStatus termination_status_;
363 int exit_code_;
[email protected]9610ef242009-11-18 02:41:26364 bool starting_;
[email protected]358cb8e2011-05-25 02:12:45365 // Controls whether the child process should be terminated on browser
366 // shutdown. Default behavior is to terminate the child.
367 bool terminate_child_on_shutdown_;
[email protected]30935362012-06-28 21:26:23368#if defined(OS_ANDROID)
369 // The fd to close after creating the process.
370 int ipcfd_;
371#elif defined(OS_POSIX) && !defined(OS_MACOSX)
[email protected]9610ef242009-11-18 02:41:26372 bool zygote_;
[email protected]fb1277e82009-11-21 20:32:30373#endif
[email protected]9610ef242009-11-18 02:41:26374};
375
376
[email protected]fb1277e82009-11-21 20:32:30377ChildProcessLauncher::ChildProcessLauncher(
378#if defined(OS_WIN)
379 const FilePath& exposed_dir,
380#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:42381 bool use_zygote,
[email protected]a82af392012-02-24 04:40:20382 const base::EnvironmentVector& environ,
[email protected]fb1277e82009-11-21 20:32:30383 int ipcfd,
[email protected]9610ef242009-11-18 02:41:26384#endif
[email protected]fb1277e82009-11-21 20:32:30385 CommandLine* cmd_line,
[email protected]40da3e0c2012-10-24 22:03:38386 int child_process_id,
[email protected]fb1277e82009-11-21 20:32:30387 Client* client) {
388 context_ = new Context();
389 context_->Launch(
390#if defined(OS_WIN)
391 exposed_dir,
[email protected]30935362012-06-28 21:26:23392#elif defined(OS_ANDROID)
393 ipcfd,
[email protected]fb1277e82009-11-21 20:32:30394#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:42395 use_zygote,
[email protected]fb1277e82009-11-21 20:32:30396 environ,
397 ipcfd,
398#endif
399 cmd_line,
[email protected]40da3e0c2012-10-24 22:03:38400 child_process_id,
[email protected]fb1277e82009-11-21 20:32:30401 client);
[email protected]9610ef242009-11-18 02:41:26402}
403
404ChildProcessLauncher::~ChildProcessLauncher() {
405 context_->ResetClient();
406}
407
408bool ChildProcessLauncher::IsStarting() {
409 return context_->starting_;
410}
411
412base::ProcessHandle ChildProcessLauncher::GetHandle() {
413 DCHECK(!context_->starting_);
414 return context_->process_.handle();
415}
416
[email protected]443b80e2010-12-14 00:42:23417base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
418 int* exit_code) {
[email protected]cd69619b2010-05-05 02:41:38419 base::ProcessHandle handle = context_->process_.handle();
[email protected]f3c1d3c2011-07-25 18:50:48420 if (handle == base::kNullProcessHandle) {
421 // Process is already gone, so return the cached termination status.
422 if (exit_code)
423 *exit_code = context_->exit_code_;
424 return context_->termination_status_;
425 }
[email protected]ffb69732012-02-08 17:33:23426#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]cd69619b2010-05-05 02:41:38427 if (context_->zygote_) {
[email protected]c2c68b1f2012-02-25 00:29:15428 context_->termination_status_ = ZygoteHostImpl::GetInstance()->
[email protected]f3c1d3c2011-07-25 18:50:48429 GetTerminationStatus(handle, &context_->exit_code_);
[email protected]cd69619b2010-05-05 02:41:38430 } else
431#endif
432 {
[email protected]f3c1d3c2011-07-25 18:50:48433 context_->termination_status_ =
434 base::GetTerminationStatus(handle, &context_->exit_code_);
[email protected]cd69619b2010-05-05 02:41:38435 }
436
[email protected]f3c1d3c2011-07-25 18:50:48437 if (exit_code)
438 *exit_code = context_->exit_code_;
439
[email protected]443b80e2010-12-14 00:42:23440 // POSIX: If the process crashed, then the kernel closed the socket
441 // for it and so the child has already died by the time we get
442 // here. Since GetTerminationStatus called waitpid with WNOHANG,
443 // it'll reap the process. However, if GetTerminationStatus didn't
444 // reap the child (because it was still running), we'll need to
[email protected]cd69619b2010-05-05 02:41:38445 // Terminate via ProcessWatcher. So we can't close the handle here.
[email protected]f3c1d3c2011-07-25 18:50:48446 if (context_->termination_status_ != base::TERMINATION_STATUS_STILL_RUNNING)
[email protected]cd69619b2010-05-05 02:41:38447 context_->process_.Close();
448
[email protected]f3c1d3c2011-07-25 18:50:48449 return context_->termination_status_;
[email protected]9610ef242009-11-18 02:41:26450}
451
452void ChildProcessLauncher::SetProcessBackgrounded(bool background) {
[email protected]3e55e212011-03-24 19:45:02453 BrowserThread::PostTask(
454 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
[email protected]037edb52011-11-15 21:14:06455 base::Bind(
[email protected]3e55e212011-03-24 19:45:02456 &ChildProcessLauncher::Context::SetProcessBackgrounded,
[email protected]e2024782011-09-07 20:20:51457 GetHandle(), background));
[email protected]9610ef242009-11-18 02:41:26458}
[email protected]358cb8e2011-05-25 02:12:45459
460void ChildProcessLauncher::SetTerminateChildOnShutdown(
461 bool terminate_on_shutdown) {
462 if (context_)
463 context_->set_terminate_child_on_shutdown(terminate_on_shutdown);
464}
[email protected]130757672012-10-24 00:26:19465
466} // namespace content