1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <dirent.h>
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h>
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <fcntl.h>
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <signal.h>
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdlib.h>
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/resource.h>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/time.h>
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/types.h>
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/wait.h>
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <unistd.h>
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <limits>
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <set>
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/command_line.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h"
21513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/debug/stack_trace.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/dir_reader_posix.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/eintr_wrapper.h"
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/file_util.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/process_util.h"
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h"
293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/synchronization/waitable_event.h"
303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h"
313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread_restrictions.h"
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h"
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_MACOSX)
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <crt_externs.h>
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <sys/event.h>
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define environ (*_NSGetEnviron())
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochextern char** environ;
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42516fd388674362c6fb2de59340b85f3d92ea32d8David 'Digit' Turner#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T)
43516fd388674362c6fb2de59340b85f3d92ea32d8David 'Digit' Turner// No ucontext.h on old Android C library headers
4468a6b85744e19ade18f176a89653f1924e64f39aBen Murdochtypedef void ucontext_t;
4568a6b85744e19ade18f176a89653f1924e64f39aBen Murdoch#endif
4668a6b85744e19ade18f176a89653f1924e64f39aBen Murdoch
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base {
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds,
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       bool* success) {
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This POSIX version of this function only guarantees that we wait no less
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // than |wait_milliseconds| for the process to exit.  The child process may
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // exit sometime before the timeout has ended but we may still block for up
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to 256 milliseconds after the fact.
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // waitpid() has no direct support on POSIX for specifying a timeout, you can
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // either ask it to block indefinitely or return immediately (WNOHANG).
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // When a child process terminates a SIGCHLD signal is sent to the parent.
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Catching this signal would involve installing a signal handler which may
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // affect other parts of the application and would be difficult to debug.
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Our strategy is to call waitpid() once up front to check if the process
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // has already exited, otherwise to loop for wait_milliseconds, sleeping for
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // at most 256 milliseconds each time using usleep() and then calling
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // waitpid().  The amount of time we sleep starts out at 1 milliseconds, and
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we double it every 4 sleep cycles.
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // usleep() is speced to exit if a signal is received for which a handler
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // has been installed.  This means that when a SIGCHLD is sent, it will exit
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // depending on behavior external to this function.
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This function is used primarily for unit tests, if we want to use it in
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the application itself it would probably be best to examine other routes.
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int status = -1;
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  pid_t ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const int64 kMaxSleepInMicroseconds = 1 << 18;  // ~256 milliseconds.
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 max_sleep_time_usecs = 1 << 10;  // ~1 milliseconds.
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 double_sleep_time = 0;
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the process hasn't exited yet, then sleep and try again.
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time wakeup_time = Time::Now() +
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      TimeDelta::FromMilliseconds(wait_milliseconds);
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (ret_pid == 0) {
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Time now = Time::Now();
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (now > wakeup_time)
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Guaranteed to be non-negative!
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int64 sleep_time_usecs = (wakeup_time - now).InMicroseconds();
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Sleep for a bit while we wait for the process to finish.
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (sleep_time_usecs > max_sleep_time_usecs)
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      sleep_time_usecs = max_sleep_time_usecs;
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // usleep() will return 0 and set errno to EINTR on receipt of a signal
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // such as SIGCHLD.
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    usleep(sleep_time_usecs);
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) &&
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        (double_sleep_time++ % 4 == 0)) {
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      max_sleep_time_usecs *= 2;
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (success)
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *success = (ret_pid != -1);
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return status;
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
112201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid StackDumpSignalHandler(int signal, siginfo_t* info, ucontext_t* context) {
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LOG(ERROR) << "Received signal " << signal;
114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  debug::StackTrace().PrintBacktrace();
115201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
116201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // TODO(shess): Port to Linux.
117201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#if defined(OS_MACOSX)
118201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // TODO(shess): Port to 64-bit.
119201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#if ARCH_CPU_32_BITS
120201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  char buf[1024];
121201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  size_t len;
122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // NOTE: Even |snprintf()| is not on the approved list for signal
124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // handlers, but buffered I/O is definitely not on the list due to
125201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // potential for |malloc()|.
126201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  len = static_cast<size_t>(
127201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      snprintf(buf, sizeof(buf),
128201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               "ax: %x, bx: %x, cx: %x, dx: %x\n",
129201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__eax,
130201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__ebx,
131201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__ecx,
132201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__edx));
133201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
134201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
135201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  len = static_cast<size_t>(
136201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      snprintf(buf, sizeof(buf),
137201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               "di: %x, si: %x, bp: %x, sp: %x, ss: %x, flags: %x\n",
138201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__edi,
139201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__esi,
140201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__ebp,
141201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__esp,
142201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__ss,
143201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__eflags));
144201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
145201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
146201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  len = static_cast<size_t>(
147201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      snprintf(buf, sizeof(buf),
148201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               "ip: %x, cs: %x, ds: %x, es: %x, fs: %x, gs: %x\n",
149201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__eip,
150201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__cs,
151201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__ds,
152201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__es,
153201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__fs,
154201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               context->uc_mcontext->__ss.__gs));
155201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
156201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#endif  // ARCH_CPU_32_BITS
157201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#endif  // defined(OS_MACOSX)
15886e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#ifdef ANDROID
15986e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun  abort();
16086e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#else
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  _exit(1);
16286e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#endif
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ResetChildSignalHandlersToDefaults() {
1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // The previous signal handlers are likely to be meaningless in the child's
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // context so we reset them to the defaults for now. http://crbug.com/44953
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // These signal handlers are set up at least in browser_main.cc:BrowserMain
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // and process_util_posix.cc:EnableInProcessStackDumping.
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  signal(SIGHUP, SIG_DFL);
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  signal(SIGINT, SIG_DFL);
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  signal(SIGILL, SIG_DFL);
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  signal(SIGABRT, SIG_DFL);
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  signal(SIGFPE, SIG_DFL);
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  signal(SIGBUS, SIG_DFL);
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  signal(SIGSEGV, SIG_DFL);
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  signal(SIGSYS, SIG_DFL);
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  signal(SIGTERM, SIG_DFL);
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // anonymous namespace
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProcessId GetCurrentProcId() {
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return getpid();
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProcessHandle GetCurrentProcessHandle() {
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return GetCurrentProcId();
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // On Posix platforms, process handles are the same as PIDs, so we
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // don't need to do anything.
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *handle = pid;
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) {
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // On POSIX permissions are checked for each operation on process,
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // not when opening a "handle".
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return OpenProcessHandle(pid, handle);
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool OpenProcessHandleWithAccess(ProcessId pid,
205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                 uint32 access_flags,
206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                 ProcessHandle* handle) {
207731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // On POSIX permissions are checked for each operation on process,
208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // not when opening a "handle".
209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return OpenProcessHandle(pid, handle);
210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid CloseProcessHandle(ProcessHandle process) {
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // See OpenProcessHandle, nothing to do.
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return;
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProcessId GetProcId(ProcessHandle process) {
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return process;
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Attempts to kill the process identified by the given process
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// entry structure.  Ignores specified exit_code; posix can't force that.
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns true if this is successful, false otherwise.
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool KillProcess(ProcessHandle process_id, int exit_code, bool wait) {
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(process_id, 1) << " tried to kill invalid process_id";
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (process_id <= 1)
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static unsigned kMaxSleepMs = 1000;
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  unsigned sleep_ms = 4;
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool result = kill(process_id, SIGTERM) == 0;
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result && wait) {
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int tries = 60;
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The process may not end immediately due to pending I/O
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool exited = false;
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    while (tries-- > 0) {
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      pid_t pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG));
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (pid == process_id) {
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        exited = true;
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (pid == -1) {
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (errno == ECHILD) {
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // The wait may fail with ECHILD if another process also waited for
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // the same pid, causing the process state to get cleaned up.
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          exited = true;
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DPLOG(ERROR) << "Error waiting for process " << process_id;
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      usleep(sleep_ms * 1000);
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (sleep_ms < kMaxSleepMs)
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        sleep_ms *= 2;
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
25821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // If we're waiting and the child hasn't died by now, force it
25921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // with a SIGKILL.
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!exited)
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result = kill(process_id, SIGKILL) == 0;
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!result)
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DPLOG(ERROR) << "Unable to terminate process " << process_id;
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool KillProcessGroup(ProcessHandle process_group_id) {
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool result = kill(-1 * process_group_id, SIGKILL) == 0;
2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result)
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    PLOG(ERROR) << "Unable to terminate process group " << process_group_id;
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return result;
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A class to handle auto-closing of DIR*'s.
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ScopedDIRClose {
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  inline void operator()(DIR* x) const {
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (x) {
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      closedir(x);
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR;
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_LINUX)
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const rlim_t kSystemDefaultMaxFds = 8192;
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char kFDDir[] = "/proc/self/fd";
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_MACOSX)
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const rlim_t kSystemDefaultMaxFds = 256;
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char kFDDir[] = "/dev/fd";
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_SOLARIS)
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const rlim_t kSystemDefaultMaxFds = 8192;
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char kFDDir[] = "/dev/fd";
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_FREEBSD)
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const rlim_t kSystemDefaultMaxFds = 8192;
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char kFDDir[] = "/dev/fd";
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_OPENBSD)
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const rlim_t kSystemDefaultMaxFds = 256;
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char kFDDir[] = "/dev/fd";
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // DANGER: no calls to malloc are allowed from now on:
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // http://crbug.com/36678
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Get the maximum number of FDs possible.
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct rlimit nofile;
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rlim_t max_fds;
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (getrlimit(RLIMIT_NOFILE, &nofile)) {
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // getrlimit failed. Take a best guess.
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_fds = kSystemDefaultMaxFds;
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    RAW_LOG(ERROR, "getrlimit(RLIMIT_NOFILE) failed");
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_fds = nofile.rlim_cur;
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_fds > INT_MAX)
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_fds = INT_MAX;
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DirReaderPosix fd_dir(kFDDir);
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!fd_dir.IsValid()) {
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Fallback case: Try every possible fd.
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (rlim_t i = 0; i < max_fds; ++i) {
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      const int fd = static_cast<int>(i);
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        continue;
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      InjectiveMultimap::const_iterator j;
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (j = saved_mapping.begin(); j != saved_mapping.end(); j++) {
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (fd == j->dest)
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (j != saved_mapping.end())
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        continue;
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Since we're just trying to close anything we can find,
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // ignore any error return values of close().
341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ignore_result(HANDLE_EINTR(close(fd)));
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int dir_fd = fd_dir.fd();
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for ( ; fd_dir.Next(); ) {
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Skip . and .. entries.
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (fd_dir.name()[0] == '.')
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    char *endptr;
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    errno = 0;
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const long int fd = strtol(fd_dir.name(), &endptr, 10);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno)
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    InjectiveMultimap::const_iterator i;
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (i = saved_mapping.begin(); i != saved_mapping.end(); i++) {
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (fd == i->dest)
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (i != saved_mapping.end())
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (fd == dir_fd)
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // When running under Valgrind, Valgrind opens several FDs for its
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // own use and will complain if we try to close them.  All of
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // these FDs are >= |max_fds|, so we can check against that here
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // before closing.  See https://bugs.kde.org/show_bug.cgi?id=191758
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (fd < static_cast<int>(max_fds)) {
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int ret = HANDLE_EINTR(close(fd));
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DPCHECK(ret == 0);
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochchar** AlterEnvironment(const environment_vector& changes,
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        const char* const* const env) {
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned count = 0;
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned size = 0;
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // First assume that all of the current environment will be included.
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned i = 0; env[i]; i++) {
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char *const pair = env[i];
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    count++;
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size += strlen(pair) + 1 /* terminating NUL */;
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (environment_vector::const_iterator
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       j = changes.begin(); j != changes.end(); j++) {
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool found = false;
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char *pair;
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (unsigned i = 0; env[i]; i++) {
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      pair = env[i];
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const char *const equals = strchr(pair, '=');
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!equals)
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        continue;
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const unsigned keylen = equals - pair;
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (keylen == j->first.size() &&
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          memcmp(pair, j->first.data(), keylen) == 0) {
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        found = true;
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // if found, we'll either be deleting or replacing this element.
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (found) {
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      count--;
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size -= strlen(pair) + 1;
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (j->second.size())
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        found = false;
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // if !found, then we have a new element to add.
420dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!found && !j->second.empty()) {
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      count++;
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size += j->first.size() + 1 /* '=' */ + j->second.size() + 1 /* NUL */;
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  count++;  // for the final NULL
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  uint8_t *buffer = new uint8_t[sizeof(char*) * count + size];
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char **const ret = reinterpret_cast<char**>(buffer);
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned k = 0;
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char *scratch = reinterpret_cast<char*>(buffer + sizeof(char*) * count);
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned i = 0; env[i]; i++) {
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char *const pair = env[i];
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char *const equals = strchr(pair, '=');
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!equals) {
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const unsigned len = strlen(pair);
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ret[k++] = scratch;
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      memcpy(scratch, pair, len + 1);
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      scratch += len + 1;
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const unsigned keylen = equals - pair;
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool handled = false;
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (environment_vector::const_iterator
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         j = changes.begin(); j != changes.end(); j++) {
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (j->first.size() == keylen &&
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          memcmp(j->first.data(), pair, keylen) == 0) {
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (!j->second.empty()) {
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          ret[k++] = scratch;
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          memcpy(scratch, pair, keylen + 1);
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          scratch += keylen + 1;
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          memcpy(scratch, j->second.c_str(), j->second.size() + 1);
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          scratch += j->second.size() + 1;
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        handled = true;
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!handled) {
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const unsigned len = strlen(pair);
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ret[k++] = scratch;
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      memcpy(scratch, pair, len + 1);
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      scratch += len + 1;
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now handle new elements
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (environment_vector::const_iterator
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       j = changes.begin(); j != changes.end(); j++) {
471dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (j->second.empty())
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool found = false;
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (unsigned i = 0; env[i]; i++) {
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const char *const pair = env[i];
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const char *const equals = strchr(pair, '=');
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!equals)
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        continue;
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const unsigned keylen = equals - pair;
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (keylen == j->first.size() &&
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          memcmp(pair, j->first.data(), keylen) == 0) {
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        found = true;
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!found) {
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ret[k++] = scratch;
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      memcpy(scratch, j->first.data(), j->first.size());
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      scratch += j->first.size();
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *scratch++ = '=';
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      memcpy(scratch, j->second.c_str(), j->second.size() + 1);
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      scratch += j->second.size() + 1;
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     }
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ret[k] = NULL;
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ret;
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool LaunchAppImpl(
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const std::vector<std::string>& argv,
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const environment_vector& env_changes,
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const file_handle_mapping_vector& fds_to_remap,
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool wait,
5073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ProcessHandle* process_handle,
5083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool start_new_process_group) {
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  pid_t pid;
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InjectiveMultimap fd_shuffle1, fd_shuffle2;
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  fd_shuffle1.reserve(fds_to_remap.size());
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  fd_shuffle2.reserve(fds_to_remap.size());
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_array<char*> new_environ(AlterEnvironment(env_changes, environ));
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  pid = fork();
517dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (pid < 0) {
518dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PLOG(ERROR) << "fork";
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
520dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (pid == 0) {
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Child process
5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // DANGER: fork() rule: in the child, if you don't end up doing exec*(),
525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // you call _exit() instead of exit(). This is because _exit() does not
526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // call any previously-registered (in the parent) exit handlers, which
527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // might do things like block waiting for threads that don't even exist
528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // in the child.
529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If a child process uses the readline library, the process block forever.
531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // In BSD like OSes including OS X it is safe to assign /dev/null as stdin.
532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // See http://crbug.com/56596.
533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    int null_fd = HANDLE_EINTR(open("/dev/null", O_RDONLY));
534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (null_fd < 0) {
535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      RAW_LOG(ERROR, "Failed to open /dev/null");
53686e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#ifdef ANDROID
53786e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun      abort();
53886e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#else
539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      _exit(127);
54086e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#endif
541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    file_util::ScopedFD null_fd_closer(&null_fd);
544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    int new_fd = HANDLE_EINTR(dup2(null_fd, STDIN_FILENO));
545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (new_fd != STDIN_FILENO) {
546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      RAW_LOG(ERROR, "Failed to dup /dev/null for stdin");
54786e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#ifdef ANDROID
54886e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun      abort();
54986e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#else
550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      _exit(127);
55186e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#endif
552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (start_new_process_group) {
5553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Instead of inheriting the process group ID of the parent, the child
5563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // starts off a new process group with pgid equal to its process ID.
557dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (setpgid(0, 0) < 0) {
558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        RAW_LOG(ERROR, "setpgid failed");
55986e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#ifdef ANDROID
56086e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun        abort();
56186e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#else
562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        _exit(127);
56386e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#endif
564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
5653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_MACOSX)
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RestoreDefaultExceptionHandler();
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ResetChildSignalHandlersToDefaults();
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if 0
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // When debugging it can be helpful to check that we really aren't making
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // any hidden calls to malloc.
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void *malloc_thunk =
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095);
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    memset(reinterpret_cast<void*>(malloc), 0xff, 8);
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // DANGER: no calls to malloc are allowed from now on:
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // http://crbug.com/36678
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (file_handle_mapping_vector::const_iterator
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        it = fds_to_remap.begin(); it != fds_to_remap.end(); ++it) {
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      fd_shuffle1.push_back(InjectionArc(it->first, it->second, false));
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      fd_shuffle2.push_back(InjectionArc(it->first, it->second, false));
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    environ = new_environ.get();
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // fd_shuffle1 is mutated by this call because it cannot malloc.
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!ShuffleFileDescriptors(&fd_shuffle1))
59486e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#ifdef ANDROID
59586e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun      abort();
59686e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#else
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      _exit(127);
59886e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#endif
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CloseSuperfluousFds(fd_shuffle2);
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (size_t i = 0; i < argv.size(); i++)
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      argv_cstr[i] = const_cast<char*>(argv[i].c_str());
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    argv_cstr[argv.size()] = NULL;
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    execvp(argv_cstr[0], argv_cstr.get());
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    RAW_LOG(ERROR, "LaunchApp: failed to execvp:");
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    RAW_LOG(ERROR, argv_cstr[0]);
60886e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#ifdef ANDROID
60986e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun    abort();
61086e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#else
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    _exit(127);
61286e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#endif
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Parent process
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (wait) {
61621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // While this isn't strictly disk IO, waiting for another process to
61721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // finish is the sort of thing ThreadRestrictions is trying to prevent.
61821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      base::ThreadRestrictions::AssertIOAllowed();
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0));
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DPCHECK(ret > 0);
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (process_handle)
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      *process_handle = pid;
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool LaunchApp(
6313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::vector<std::string>& argv,
6323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const environment_vector& env_changes,
6333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const file_handle_mapping_vector& fds_to_remap,
6343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool wait,
6353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ProcessHandle* process_handle) {
6363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return LaunchAppImpl(argv, env_changes, fds_to_remap,
6373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       wait, process_handle, false);
6383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool LaunchAppInNewProcessGroup(
6413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::vector<std::string>& argv,
6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const environment_vector& env_changes,
6433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const file_handle_mapping_vector& fds_to_remap,
6443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool wait,
6453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ProcessHandle* process_handle) {
6463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return LaunchAppImpl(argv, env_changes, fds_to_remap, wait,
6473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       process_handle, true);
6483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LaunchApp(const std::vector<std::string>& argv,
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               const file_handle_mapping_vector& fds_to_remap,
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               bool wait, ProcessHandle* process_handle) {
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::environment_vector no_env;
654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return LaunchApp(argv, no_env, fds_to_remap, wait, process_handle);
655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LaunchApp(const CommandLine& cl,
658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               bool wait, bool start_hidden,
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               ProcessHandle* process_handle) {
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file_handle_mapping_vector no_files;
661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return LaunchApp(cl.argv(), no_files, wait, process_handle);
662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProcessMetrics::~ProcessMetrics() { }
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EnableTerminationOnHeapCorruption() {
667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // On POSIX, there nothing to do AFAIK.
668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EnableInProcessStackDumping() {
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // When running in an application, our code typically expects SIGPIPE
672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // to be ignored.  Therefore, when testing that same code, it should run
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // with SIGPIPE ignored as well.
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct sigaction action;
675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  action.sa_handler = SIG_IGN;
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  action.sa_flags = 0;
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  sigemptyset(&action.sa_mask);
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool success = (sigaction(SIGPIPE, &action, NULL) == 0);
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
680201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  sig_t handler = reinterpret_cast<sig_t>(&StackDumpSignalHandler);
681201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  success &= (signal(SIGILL, handler) != SIG_ERR);
682201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  success &= (signal(SIGABRT, handler) != SIG_ERR);
683201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  success &= (signal(SIGFPE, handler) != SIG_ERR);
684201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  success &= (signal(SIGBUS, handler) != SIG_ERR);
685201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  success &= (signal(SIGSEGV, handler) != SIG_ERR);
686201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  success &= (signal(SIGSYS, handler) != SIG_ERR);
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return success;
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid RaiseProcessToHighPriority() {
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // On POSIX, we don't actually do anything here.  We could try to nice() or
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // setpriority() or sched_getscheduler, but these all require extra rights.
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
69621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenTerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
69721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int status = 0;
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const pid_t result = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == -1) {
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PLOG(ERROR) << "waitpid(" << handle << ")";
70121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (exit_code)
70221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      *exit_code = 0;
70321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return TERMINATION_STATUS_NORMAL_TERMINATION;
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (result == 0) {
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // the child hasn't exited yet.
70621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (exit_code)
70721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      *exit_code = 0;
70821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return TERMINATION_STATUS_STILL_RUNNING;
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
71121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (exit_code)
71221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    *exit_code = status;
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (WIFSIGNALED(status)) {
715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    switch (WTERMSIG(status)) {
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case SIGABRT:
71721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case SIGBUS:
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case SIGFPE:
71921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case SIGILL:
72021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case SIGSEGV:
72121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        return TERMINATION_STATUS_PROCESS_CRASHED;
72221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case SIGINT:
72321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case SIGKILL:
72421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case SIGTERM:
72521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        return TERMINATION_STATUS_PROCESS_WAS_KILLED;
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      default:
72721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        break;
728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
73221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return TERMINATION_STATUS_ABNORMAL_TERMINATION;
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return TERMINATION_STATUS_NORMAL_TERMINATION;
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool WaitForExitCode(ProcessHandle handle, int* exit_code) {
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int status;
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) {
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (WIFEXITED(status)) {
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *exit_code = WEXITSTATUS(status);
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If it didn't exit cleanly, it must have been signaled.
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(WIFSIGNALED(status));
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return false;
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code,
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                int64 timeout_milliseconds) {
756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool waitpid_success = false;
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int status = WaitpidWithTimeout(handle, timeout_milliseconds,
758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  &waitpid_success);
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (status == -1)
760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!waitpid_success)
762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (WIFSIGNALED(status)) {
764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *exit_code = -1;
765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
767ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (WIFEXITED(status)) {
768ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *exit_code = WEXITSTATUS(status);
769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
770ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
771ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return false;
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
774dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_MACOSX)
775dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Using kqueue on Mac so that we can wait on non-child processes.
776dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// We can't use kqueues on child processes because we need to reap
777dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// our own children using wait.
778dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic bool WaitForSingleNonChildProcess(ProcessHandle handle,
779dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                         int64 wait_milliseconds) {
780dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int kq = kqueue();
781dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (kq == -1) {
782dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PLOG(ERROR) << "kqueue";
783dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
784dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
785dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
786dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  struct kevent change = { 0 };
787dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
788dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
789dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  struct timespec spec;
790dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  struct timespec *spec_ptr;
791dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (wait_milliseconds != base::kNoTimeout) {
792dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    time_t sec = static_cast<time_t>(wait_milliseconds / 1000);
793dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    wait_milliseconds = wait_milliseconds - (sec * 1000);
794dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    spec.tv_sec = sec;
795dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    spec.tv_nsec = wait_milliseconds * 1000000L;
796dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    spec_ptr = &spec;
797dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
798dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    spec_ptr = NULL;
799dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
800dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
801dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  while(true) {
802dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    struct kevent event = { 0 };
803dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int event_count = HANDLE_EINTR(kevent(kq, &change, 1, &event, 1, spec_ptr));
804dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (close(kq) != 0) {
805dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      PLOG(ERROR) << "close";
806dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
807dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (event_count < 0) {
808dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      PLOG(ERROR) << "kevent";
809dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return false;
810dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if (event_count == 0) {
811dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (wait_milliseconds != base::kNoTimeout) {
812dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        // Timed out.
813dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return false;
814dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
815dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if ((event_count == 1) &&
816dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               (handle == static_cast<pid_t>(event.ident)) &&
817dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               (event.filter == EVFILT_PROC)) {
818dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (event.fflags == NOTE_EXIT) {
819dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return true;
820dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      } else if (event.flags == EV_ERROR) {
821dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(ERROR) << "kevent error " << event.data;
822dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return false;
823dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      } else {
824dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        NOTREACHED();
825dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return false;
826dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
827dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else {
828dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NOTREACHED();
829dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return false;
830dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
831dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
832dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
833dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif  // OS_MACOSX
834dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) {
836dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ProcessHandle parent_pid = GetParentProcessId(handle);
837dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ProcessHandle our_pid = Process::Current().handle();
838dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (parent_pid != our_pid) {
839dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_MACOSX)
840dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // On Mac we can wait on non child processes.
841dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return WaitForSingleNonChildProcess(handle, wait_milliseconds);
842dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#else
843dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Currently on Linux we can't handle non child processes.
844dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    NOTIMPLEMENTED();
845dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif  // OS_MACOSX
846dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool waitpid_success;
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int status;
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (wait_milliseconds == base::kNoTimeout)
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    waitpid_success = (HANDLE_EINTR(waitpid(handle, &status, 0)) != -1);
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    status = WaitpidWithTimeout(handle, wait_milliseconds, &waitpid_success);
853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (status != -1) {
854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(waitpid_success);
855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return WIFEXITED(status);
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint64 TimeValToMicroseconds(const struct timeval& tv) {
862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const int kMicrosecondsPerSecond = 1000000;
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 ret = tv.tv_sec;  // Avoid (int * int) integer overflow.
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ret *= kMicrosecondsPerSecond;
865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ret += tv.tv_usec;
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ret;
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Executes the application specified by |cl| and wait for it to exit. Stores
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the output (stdout) in |output|. If |do_search_path| is set, it searches the
871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// path for the application; in that case, |envp| must be null, and it will use
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the current environment. If |do_search_path| is false, |cl| should fully
873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// specify the path of the application, and |envp| will be used as the
874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// environment. Redirects stderr to /dev/null. Returns true on success
875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (application launched and exited cleanly, with exit code indicating success).
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic bool GetAppOutputInternal(const CommandLine& cl, char* const envp[],
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 std::string* output, size_t max_output,
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 bool do_search_path) {
87921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Doing a blocking wait for another command to finish counts as IO.
88021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  base::ThreadRestrictions::AssertIOAllowed();
88121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int pipe_fd[2];
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  pid_t pid;
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InjectiveMultimap fd_shuffle1, fd_shuffle2;
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::vector<std::string>& argv = cl.argv();
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  fd_shuffle1.reserve(3);
889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  fd_shuffle2.reserve(3);
890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Either |do_search_path| should be false or |envp| should be null, but not
892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // both.
893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!do_search_path ^ !envp);
894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (pipe(pipe_fd) < 0)
896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (pid = fork()) {
899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case -1:  // error
900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      close(pipe_fd[0]);
901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      close(pipe_fd[1]);
902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case 0:  // child
904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      {
905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_MACOSX)
906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        RestoreDefaultExceptionHandler();
907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // DANGER: no calls to malloc are allowed from now on:
909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // http://crbug.com/36678
910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // Obscure fork() rule: in the child, if you don't end up doing exec*(),
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // you call _exit() instead of exit(). This is because _exit() does not
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // call any previously-registered (in the parent) exit handlers, which
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // might do things like block waiting for threads that don't even exist
915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // in the child.
916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        int dev_null = open("/dev/null", O_WRONLY);
917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (dev_null < 0)
91886e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#ifdef ANDROID
91986e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun          abort();
92086e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#else
921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          _exit(127);
92286e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#endif
923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true));
926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Adding another element here? Remeber to increase the argument to
928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // reserve(), above.
929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        std::copy(fd_shuffle1.begin(), fd_shuffle1.end(),
931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  std::back_inserter(fd_shuffle2));
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (!ShuffleFileDescriptors(&fd_shuffle1))
93486e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#ifdef ANDROID
93586e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun          abort();
93686e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#else
937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          _exit(127);
93886e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#endif
939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        CloseSuperfluousFds(fd_shuffle2);
941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        for (size_t i = 0; i < argv.size(); i++)
943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          argv_cstr[i] = const_cast<char*>(argv[i].c_str());
944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        argv_cstr[argv.size()] = NULL;
945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (do_search_path)
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          execvp(argv_cstr[0], argv_cstr.get());
947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        else
948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          execve(argv_cstr[0], argv_cstr.get(), envp);
94986e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#ifdef ANDROID
95086e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun        abort();
95186e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#else
952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        _exit(127);
95386e0fcf830dcbada802ea2de22904e912dda5384Selim Gurun#endif
954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:  // parent
956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      {
957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // Close our writing end of pipe now. Otherwise later read would not
958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // be able to detect end of child's output (in theory we could still
959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // write to the pipe).
960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        close(pipe_fd[1]);
961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        output->clear();
963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        char buffer[256];
964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        size_t output_buf_left = max_output;
965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ssize_t bytes_read = 1;  // A lie to properly handle |max_output == 0|
966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 // case in the logic below.
967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        while (output_buf_left > 0) {
969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer,
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    std::min(output_buf_left, sizeof(buffer))));
971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          if (bytes_read <= 0)
972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          output->append(buffer, bytes_read);
974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          output_buf_left -= static_cast<size_t>(bytes_read);
975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        close(pipe_fd[0]);
977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // Always wait for exit code (even if we know we'll declare success).
979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        int exit_code = EXIT_FAILURE;
980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        bool success = WaitForExitCode(pid, &exit_code);
981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // If we stopped because we read as much as we wanted, we always declare
983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // success (because the child may exit due to |SIGPIPE|).
984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (output_buf_left || bytes_read <= 0) {
985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          if (!success || exit_code != EXIT_SUCCESS)
986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return false;
987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return true;
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool GetAppOutput(const CommandLine& cl, std::string* output) {
995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Run |execve()| with the current environment and store "unlimited" data.
996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return GetAppOutputInternal(cl, NULL, output,
997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                              std::numeric_limits<std::size_t>::max(), true);
998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(viettrungluu): Conceivably, we should have a timeout as well, so we
1001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// don't hang if what we're calling hangs.
1002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool GetAppOutputRestricted(const CommandLine& cl,
1003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            std::string* output, size_t max_output) {
1004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Run |execve()| with the empty environment.
1005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char* const empty_environ = NULL;
1006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return GetAppOutputInternal(cl, &empty_environ, output, max_output, false);
1007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
100921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool WaitForProcessesToExit(const FilePath::StringType& executable_name,
1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            int64 wait_milliseconds,
1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            const ProcessFilter* filter) {
1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool result = false;
1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(port): This is inefficient, but works if there are multiple procs.
1015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(port): use waitpid to avoid leaving zombies around
1016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::Time end_time = base::Time::Now() +
1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::TimeDelta::FromMilliseconds(wait_milliseconds);
1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  do {
1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NamedProcessIterator iter(executable_name, filter);
1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!iter.NextProcessEntry()) {
1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result = true;
1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
10253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::PlatformThread::Sleep(100);
1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while ((base::Time::Now() - end_time) > base::TimeDelta());
1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
103121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool CleanupProcesses(const FilePath::StringType& executable_name,
1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      int64 wait_milliseconds,
1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      int exit_code,
1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      const ProcessFilter* filter) {
1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool exited_cleanly =
1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      WaitForProcessesToExit(executable_name, wait_milliseconds,
1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             filter);
1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!exited_cleanly)
1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    KillProcesses(executable_name, exit_code, filter);
1040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return exited_cleanly;
1041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace base
1044