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