blob: fb5ed467cb50629adaf8e2430defa8b31d98beeb [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]e63c4d72011-05-31 22:38:2926#elif defined(OS_MACOSX)
[email protected]ed0fbe62011-06-23 18:32:1127#include "content/browser/mach_broker_mac.h"
[email protected]30935362012-06-28 21:26:2328#elif defined(OS_ANDROID)
29#include "base/android/jni_android.h"
30#include "content/browser/android/sandboxed_process_launcher.h"
[email protected]e63c4d72011-05-31 22:38:2931#elif defined(OS_POSIX)
[email protected]3b63f8f42011-03-28 01:54:1532#include "base/memory/singleton.h"
[email protected]a01efd22011-03-01 00:38:3233#include "content/browser/renderer_host/render_sandbox_host_linux.h"
[email protected]c2c68b1f2012-02-25 00:29:1534#include "content/browser/zygote_host_impl_linux.h"
[email protected]9610ef242009-11-18 02:41:2635#endif
36
[email protected]fb1277e82009-11-21 20:32:3037#if defined(OS_POSIX)
38#include "base/global_descriptors_posix.h"
39#endif
40
[email protected]631bb742011-11-02 11:29:3941using content::BrowserThread;
42
[email protected]9610ef242009-11-18 02:41:2643// Having the functionality of ChildProcessLauncher be in an internal
44// ref counted object allows us to automatically terminate the process when the
45// parent class destructs, while still holding on to state that we need.
46class ChildProcessLauncher::Context
47 : public base::RefCountedThreadSafe<ChildProcessLauncher::Context> {
48 public:
[email protected]fb1277e82009-11-21 20:32:3049 Context()
[email protected]18cbea32010-10-13 19:56:0050 : client_(NULL),
51 client_thread_id_(BrowserThread::UI),
[email protected]f3c1d3c2011-07-25 18:50:4852 termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
53 exit_code_(content::RESULT_CODE_NORMAL_EXIT),
[email protected]08c426a2012-04-10 20:37:3354 starting_(true)
[email protected]ffb69732012-02-08 17:33:2355#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]fb1277e82009-11-21 20:32:3056 , zygote_(false)
57#endif
58 {
[email protected]08c426a2012-04-10 20:37:3359#if defined(OS_POSIX)
60 terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()->
61 HasSwitch(switches::kRendererCleanExit);
62#else
63 terminate_child_on_shutdown_ = true;
64#endif
[email protected]fb1277e82009-11-21 20:32:3065 }
[email protected]9610ef242009-11-18 02:41:2666
[email protected]fb1277e82009-11-21 20:32:3067 void Launch(
68#if defined(OS_WIN)
69 const FilePath& exposed_dir,
[email protected]30935362012-06-28 21:26:2370#elif defined(OS_ANDROID)
71 int ipcfd,
[email protected]fb1277e82009-11-21 20:32:3072#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:4273 bool use_zygote,
[email protected]a82af392012-02-24 04:40:2074 const base::EnvironmentVector& environ,
[email protected]fb1277e82009-11-21 20:32:3075 int ipcfd,
76#endif
77 CommandLine* cmd_line,
78 Client* client) {
[email protected]9610ef242009-11-18 02:41:2679 client_ = client;
80
[email protected]d04e7662010-10-10 22:24:4881 CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_));
[email protected]9610ef242009-11-18 02:41:2682
[email protected]30935362012-06-28 21:26:2383#if defined(OS_ANDROID)
84 // We need to close the client end of the IPC channel to reliably detect
85 // child termination. We will close this fd after we create the child
86 // process which is asynchronous on Android.
87 ipcfd_ = ipcfd;
88#endif
[email protected]d04e7662010-10-10 22:24:4889 BrowserThread::PostTask(
90 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
[email protected]037edb52011-11-15 21:14:0691 base::Bind(
[email protected]fb1277e82009-11-21 20:32:3092 &Context::LaunchInternal,
[email protected]e2024782011-09-07 20:20:5193 make_scoped_refptr(this),
94 client_thread_id_,
[email protected]fb1277e82009-11-21 20:32:3095#if defined(OS_WIN)
96 exposed_dir,
[email protected]30935362012-06-28 21:26:2397#elif defined(OS_ANDROID)
98 ipcfd,
[email protected]eb1bd832010-05-18 20:39:5899#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:42100 use_zygote,
[email protected]3d2217d2009-11-23 21:26:47101 environ,
[email protected]fb1277e82009-11-21 20:32:30102 ipcfd,
103#endif
104 cmd_line));
[email protected]9610ef242009-11-18 02:41:26105 }
106
[email protected]30935362012-06-28 21:26:23107#if defined(OS_ANDROID)
108 static void OnSandboxedProcessStarted(
109 // |this_object| is NOT thread safe. Only use it to post a task back.
110 scoped_refptr<Context> this_object,
111 BrowserThread::ID client_thread_id,
112 base::ProcessHandle handle) {
113 if (BrowserThread::CurrentlyOn(client_thread_id)) {
114 // This is always invoked on the UI thread which is commonly the
115 // |client_thread_id| so we can shortcut one PostTask.
116 this_object->Notify(handle);
117 } else {
118 BrowserThread::PostTask(
119 client_thread_id, FROM_HERE,
120 base::Bind(
121 &ChildProcessLauncher::Context::Notify,
122 this_object,
123 handle));
124 }
125 }
126#endif
127
[email protected]9610ef242009-11-18 02:41:26128 void ResetClient() {
129 // No need for locking as this function gets called on the same thread that
130 // client_ would be used.
[email protected]d04e7662010-10-10 22:24:48131 CHECK(BrowserThread::CurrentlyOn(client_thread_id_));
[email protected]9610ef242009-11-18 02:41:26132 client_ = NULL;
133 }
134
[email protected]358cb8e2011-05-25 02:12:45135 void set_terminate_child_on_shutdown(bool terminate_on_shutdown) {
136 terminate_child_on_shutdown_ = terminate_on_shutdown;
137 }
138
[email protected]9610ef242009-11-18 02:41:26139 private:
140 friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>;
141 friend class ChildProcessLauncher;
142
143 ~Context() {
144 Terminate();
145 }
146
[email protected]e2024782011-09-07 20:20:51147 static void LaunchInternal(
148 // |this_object| is NOT thread safe. Only use it to post a task back.
149 scoped_refptr<Context> this_object,
150 BrowserThread::ID client_thread_id,
[email protected]fb1277e82009-11-21 20:32:30151#if defined(OS_WIN)
152 const FilePath& exposed_dir,
[email protected]30935362012-06-28 21:26:23153#elif defined(OS_ANDROID)
154 int ipcfd,
[email protected]fb1277e82009-11-21 20:32:30155#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:42156 bool use_zygote,
[email protected]a82af392012-02-24 04:40:20157 const base::EnvironmentVector& env,
[email protected]fb1277e82009-11-21 20:32:30158 int ipcfd,
159#endif
160 CommandLine* cmd_line) {
[email protected]9610ef242009-11-18 02:41:26161 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line);
[email protected]2ce26c432011-09-19 17:08:12162
[email protected]9610ef242009-11-18 02:41:26163#if defined(OS_WIN)
[email protected]30935362012-06-28 21:26:23164 base::ProcessHandle handle = sandbox::StartProcessWithAccess(
165 cmd_line, exposed_dir);
166#elif defined(OS_ANDROID)
167 std::string process_type =
168 cmd_line->GetSwitchValueASCII(switches::kProcessType);
169 base::GlobalDescriptors::Mapping files_to_register;
170 files_to_register.push_back(std::pair<base::GlobalDescriptors::Key, int>(
171 kPrimaryIPCChannel, ipcfd));
172 content::GetContentClient()->browser()->
173 GetAdditionalMappedFilesForChildProcess(*cmd_line, &files_to_register);
174
175 content::StartSandboxedProcess(cmd_line->argv(),
176 ipcfd, files_to_register,
177 base::Bind(&ChildProcessLauncher::Context::OnSandboxedProcessStarted,
178 this_object, client_thread_id));
179
[email protected]9610ef242009-11-18 02:41:26180#elif defined(OS_POSIX)
[email protected]30935362012-06-28 21:26:23181 base::ProcessHandle handle = base::kNullProcessHandle;
[email protected]2ce26c432011-09-19 17:08:12182 // We need to close the client end of the IPC channel
183 // to reliably detect child termination.
184 file_util::ScopedFD ipcfd_closer(&ipcfd);
[email protected]9610ef242009-11-18 02:41:26185
[email protected]54457f32011-04-15 22:05:29186 std::string process_type =
187 cmd_line->GetSwitchValueASCII(switches::kProcessType);
[email protected]a1733df2012-06-22 11:24:18188 base::GlobalDescriptors::Mapping files_to_register;
189 files_to_register.push_back(std::pair<base::GlobalDescriptors::Key, int>(
190 kPrimaryIPCChannel, ipcfd));
[email protected]30935362012-06-28 21:26:23191#if !defined(OS_MACOSX)
[email protected]a1733df2012-06-22 11:24:18192 content::GetContentClient()->browser()->
193 GetAdditionalMappedFilesForChildProcess(*cmd_line, &files_to_register);
[email protected]7c4ea142010-01-26 05:15:42194 if (use_zygote) {
[email protected]c2c68b1f2012-02-25 00:29:15195 handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(),
[email protected]a1733df2012-06-22 11:24:18196 files_to_register,
[email protected]c2c68b1f2012-02-25 00:29:15197 process_type);
[email protected]7c4ea142010-01-26 05:15:42198 } else
199 // Fall through to the normal posix case below when we're not zygoting.
[email protected]30935362012-06-28 21:26:23200#endif // !defined(OS_MACOSX)
[email protected]fb1277e82009-11-21 20:32:30201 {
[email protected]a1733df2012-06-22 11:24:18202 // Convert FD mapping to FileHandleMappingVector
[email protected]a82af392012-02-24 04:40:20203 base::FileHandleMappingVector fds_to_map;
[email protected]a1733df2012-06-22 11:24:18204 for (size_t i = 0; i < files_to_register.size(); ++i) {
205 const base::GlobalDescriptors::KeyFDPair& id_file =
206 files_to_register[i];
[email protected]54457f32011-04-15 22:05:29207 fds_to_map.push_back(std::make_pair(
[email protected]a1733df2012-06-22 11:24:18208 id_file.second,
209 id_file.first + base::GlobalDescriptors::kBaseDescriptor));
[email protected]9610ef242009-11-18 02:41:26210 }
[email protected]a1733df2012-06-22 11:24:18211
[email protected]30935362012-06-28 21:26:23212#if !defined(OS_MACOSX)
[email protected]b80f68432011-05-02 17:22:30213 if (process_type == switches::kRendererProcess) {
[email protected]fb1277e82009-11-21 20:32:30214 const int sandbox_fd =
[email protected]d3c6c0d72010-12-09 08:15:04215 RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
[email protected]fb1277e82009-11-21 20:32:30216 fds_to_map.push_back(std::make_pair(
217 sandbox_fd,
218 kSandboxIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
219 }
[email protected]30935362012-06-28 21:26:23220#endif // defined(OS_MACOSX)
[email protected]9610ef242009-11-18 02:41:26221
[email protected]84b2d1d2011-09-01 21:44:24222 // Actually launch the app.
223 base::LaunchOptions options;
224 options.environ = &env;
225 options.fds_to_remap = &fds_to_map;
226
[email protected]c0028792010-01-12 00:39:15227#if defined(OS_MACOSX)
[email protected]84b2d1d2011-09-01 21:44:24228 // Use synchronization to make sure that the MachBroker is ready to
229 // receive a check-in from the new process before the new process
230 // actually tries to check in.
231 base::LaunchSynchronizationHandle synchronization_handle;
232 options.synchronize = &synchronization_handle;
233#endif // defined(OS_MACOSX)
234
235 bool launched = base::LaunchProcess(*cmd_line, options, &handle);
236
237#if defined(OS_MACOSX)
238 if (launched) {
[email protected]dc8caba2010-12-13 16:52:35239 MachBroker* broker = MachBroker::GetInstance();
[email protected]84b2d1d2011-09-01 21:44:24240 {
241 base::AutoLock lock(broker->GetLock());
[email protected]b88a7492010-09-17 12:28:32242
[email protected]84b2d1d2011-09-01 21:44:24243 // Make sure the MachBroker is running, and inform it to expect a
244 // check-in from the new process.
245 broker->EnsureRunning();
[email protected]b88a7492010-09-17 12:28:32246 broker->AddPlaceholderForPid(handle);
[email protected]84b2d1d2011-09-01 21:44:24247 }
248
249 // Now that the MachBroker is ready, the child may continue.
250 base::LaunchSynchronize(synchronization_handle);
251 }
252#endif // defined(OS_MACOSX)
253
[email protected]c0028792010-01-12 00:39:15254 if (!launched)
[email protected]9610ef242009-11-18 02:41:26255 handle = base::kNullProcessHandle;
256 }
[email protected]c0028792010-01-12 00:39:15257#endif // else defined(OS_POSIX)
[email protected]30935362012-06-28 21:26:23258#if !defined(OS_ANDROID)
259 BrowserThread::PostTask(
260 client_thread_id, FROM_HERE,
261 base::Bind(
262 &Context::Notify,
263 this_object.get(),
264#if defined(OS_POSIX) && !defined(OS_MACOSX)
265 use_zygote,
[email protected]fb1277e82009-11-21 20:32:30266#endif
[email protected]30935362012-06-28 21:26:23267 handle));
268#endif // !defined(OS_ANDROID)
[email protected]9610ef242009-11-18 02:41:26269 }
270
[email protected]cd69619b2010-05-05 02:41:38271 void Notify(
[email protected]ffb69732012-02-08 17:33:23272#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]fb1277e82009-11-21 20:32:30273 bool zygote,
274#endif
275 base::ProcessHandle handle) {
[email protected]30935362012-06-28 21:26:23276#if defined(OS_ANDROID)
277 // Finally close the ipcfd
278 file_util::ScopedFD ipcfd_closer(&ipcfd_);
279#endif
[email protected]9610ef242009-11-18 02:41:26280 starting_ = false;
281 process_.set_handle(handle);
[email protected]e51ddf252011-10-12 17:33:21282 if (!handle)
283 LOG(ERROR) << "Failed to launch child process";
284
[email protected]ffb69732012-02-08 17:33:23285#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]9610ef242009-11-18 02:41:26286 zygote_ = zygote;
[email protected]fb1277e82009-11-21 20:32:30287#endif
[email protected]9610ef242009-11-18 02:41:26288 if (client_) {
289 client_->OnProcessLaunched();
290 } else {
291 Terminate();
292 }
293 }
294
295 void Terminate() {
296 if (!process_.handle())
297 return;
298
[email protected]358cb8e2011-05-25 02:12:45299 if (!terminate_child_on_shutdown_)
300 return;
301
[email protected]9610ef242009-11-18 02:41:26302 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So
303 // don't this on the UI/IO threads.
[email protected]d04e7662010-10-10 22:24:48304 BrowserThread::PostTask(
305 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
[email protected]037edb52011-11-15 21:14:06306 base::Bind(
[email protected]e2024782011-09-07 20:20:51307 &Context::TerminateInternal,
[email protected]ffb69732012-02-08 17:33:23308#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]fb1277e82009-11-21 20:32:30309 zygote_,
310#endif
311 process_.handle()));
[email protected]9610ef242009-11-18 02:41:26312 process_.set_handle(base::kNullProcessHandle);
313 }
314
[email protected]e2024782011-09-07 20:20:51315 static void SetProcessBackgrounded(base::ProcessHandle handle,
316 bool background) {
317 base::Process process(handle);
318 process.SetProcessBackgrounded(background);
[email protected]3e55e212011-03-24 19:45:02319 }
320
[email protected]fb1277e82009-11-21 20:32:30321 static void TerminateInternal(
[email protected]ffb69732012-02-08 17:33:23322#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]fb1277e82009-11-21 20:32:30323 bool zygote,
324#endif
325 base::ProcessHandle handle) {
[email protected]30935362012-06-28 21:26:23326#if defined(OS_ANDROID)
327 LOG(INFO) << "ChromeProcess: Stopping process with handle " << handle;
328 content::StopSandboxedProcess(handle);
329#else
[email protected]9610ef242009-11-18 02:41:26330 base::Process process(handle);
331 // Client has gone away, so just kill the process. Using exit code 0
332 // means that UMA won't treat this as a crash.
[email protected]1fcfb202011-07-19 19:53:14333 process.Terminate(content::RESULT_CODE_NORMAL_EXIT);
[email protected]9610ef242009-11-18 02:41:26334 // On POSIX, we must additionally reap the child.
335#if defined(OS_POSIX)
[email protected]30935362012-06-28 21:26:23336#if !defined(OS_MACOSX)
[email protected]fb1277e82009-11-21 20:32:30337 if (zygote) {
[email protected]9610ef242009-11-18 02:41:26338 // If the renderer was created via a zygote, we have to proxy the reaping
339 // through the zygote process.
[email protected]c2c68b1f2012-02-25 00:29:15340 ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(handle);
[email protected]fb1277e82009-11-21 20:32:30341 } else
[email protected]e63c4d72011-05-31 22:38:29342#endif // !OS_MACOSX
[email protected]fb1277e82009-11-21 20:32:30343 {
[email protected]eaac71592011-11-23 18:32:00344 base::EnsureProcessTerminated(handle);
[email protected]9610ef242009-11-18 02:41:26345 }
[email protected]e36e86f2009-12-15 11:55:08346#endif // OS_POSIX
[email protected]9610ef242009-11-18 02:41:26347 process.Close();
[email protected]30935362012-06-28 21:26:23348#endif // defined(OS_ANDROID)
[email protected]9610ef242009-11-18 02:41:26349 }
350
351 Client* client_;
[email protected]d04e7662010-10-10 22:24:48352 BrowserThread::ID client_thread_id_;
[email protected]9610ef242009-11-18 02:41:26353 base::Process process_;
[email protected]f3c1d3c2011-07-25 18:50:48354 base::TerminationStatus termination_status_;
355 int exit_code_;
[email protected]9610ef242009-11-18 02:41:26356 bool starting_;
[email protected]358cb8e2011-05-25 02:12:45357 // Controls whether the child process should be terminated on browser
358 // shutdown. Default behavior is to terminate the child.
359 bool terminate_child_on_shutdown_;
[email protected]30935362012-06-28 21:26:23360#if defined(OS_ANDROID)
361 // The fd to close after creating the process.
362 int ipcfd_;
363#elif defined(OS_POSIX) && !defined(OS_MACOSX)
[email protected]9610ef242009-11-18 02:41:26364 bool zygote_;
[email protected]fb1277e82009-11-21 20:32:30365#endif
[email protected]9610ef242009-11-18 02:41:26366};
367
368
[email protected]fb1277e82009-11-21 20:32:30369ChildProcessLauncher::ChildProcessLauncher(
370#if defined(OS_WIN)
371 const FilePath& exposed_dir,
372#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:42373 bool use_zygote,
[email protected]a82af392012-02-24 04:40:20374 const base::EnvironmentVector& environ,
[email protected]fb1277e82009-11-21 20:32:30375 int ipcfd,
[email protected]9610ef242009-11-18 02:41:26376#endif
[email protected]fb1277e82009-11-21 20:32:30377 CommandLine* cmd_line,
378 Client* client) {
379 context_ = new Context();
380 context_->Launch(
381#if defined(OS_WIN)
382 exposed_dir,
[email protected]30935362012-06-28 21:26:23383#elif defined(OS_ANDROID)
384 ipcfd,
[email protected]fb1277e82009-11-21 20:32:30385#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:42386 use_zygote,
[email protected]fb1277e82009-11-21 20:32:30387 environ,
388 ipcfd,
389#endif
390 cmd_line,
391 client);
[email protected]9610ef242009-11-18 02:41:26392}
393
394ChildProcessLauncher::~ChildProcessLauncher() {
395 context_->ResetClient();
396}
397
398bool ChildProcessLauncher::IsStarting() {
399 return context_->starting_;
400}
401
402base::ProcessHandle ChildProcessLauncher::GetHandle() {
403 DCHECK(!context_->starting_);
404 return context_->process_.handle();
405}
406
[email protected]443b80e2010-12-14 00:42:23407base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
408 int* exit_code) {
[email protected]cd69619b2010-05-05 02:41:38409 base::ProcessHandle handle = context_->process_.handle();
[email protected]f3c1d3c2011-07-25 18:50:48410 if (handle == base::kNullProcessHandle) {
411 // Process is already gone, so return the cached termination status.
412 if (exit_code)
413 *exit_code = context_->exit_code_;
414 return context_->termination_status_;
415 }
[email protected]ffb69732012-02-08 17:33:23416#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]cd69619b2010-05-05 02:41:38417 if (context_->zygote_) {
[email protected]c2c68b1f2012-02-25 00:29:15418 context_->termination_status_ = ZygoteHostImpl::GetInstance()->
[email protected]f3c1d3c2011-07-25 18:50:48419 GetTerminationStatus(handle, &context_->exit_code_);
[email protected]cd69619b2010-05-05 02:41:38420 } else
421#endif
422 {
[email protected]f3c1d3c2011-07-25 18:50:48423 context_->termination_status_ =
424 base::GetTerminationStatus(handle, &context_->exit_code_);
[email protected]cd69619b2010-05-05 02:41:38425 }
426
[email protected]f3c1d3c2011-07-25 18:50:48427 if (exit_code)
428 *exit_code = context_->exit_code_;
429
[email protected]443b80e2010-12-14 00:42:23430 // POSIX: If the process crashed, then the kernel closed the socket
431 // for it and so the child has already died by the time we get
432 // here. Since GetTerminationStatus called waitpid with WNOHANG,
433 // it'll reap the process. However, if GetTerminationStatus didn't
434 // reap the child (because it was still running), we'll need to
[email protected]cd69619b2010-05-05 02:41:38435 // Terminate via ProcessWatcher. So we can't close the handle here.
[email protected]f3c1d3c2011-07-25 18:50:48436 if (context_->termination_status_ != base::TERMINATION_STATUS_STILL_RUNNING)
[email protected]cd69619b2010-05-05 02:41:38437 context_->process_.Close();
438
[email protected]f3c1d3c2011-07-25 18:50:48439 return context_->termination_status_;
[email protected]9610ef242009-11-18 02:41:26440}
441
442void ChildProcessLauncher::SetProcessBackgrounded(bool background) {
[email protected]3e55e212011-03-24 19:45:02443 BrowserThread::PostTask(
444 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
[email protected]037edb52011-11-15 21:14:06445 base::Bind(
[email protected]3e55e212011-03-24 19:45:02446 &ChildProcessLauncher::Context::SetProcessBackgrounded,
[email protected]e2024782011-09-07 20:20:51447 GetHandle(), background));
[email protected]9610ef242009-11-18 02:41:26448}
[email protected]358cb8e2011-05-25 02:12:45449
450void ChildProcessLauncher::SetTerminateChildOnShutdown(
451 bool terminate_on_shutdown) {
452 if (context_)
453 context_->set_terminate_child_on_shutdown(terminate_on_shutdown);
454}