15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/process/launch.h"
69ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dirent.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/resource.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/wait.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iterator>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/allocator/type_profiler_control.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/debugger.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/stack_trace.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/files/dir_reader_posix.h"
286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/files/file_util.h"
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/scoped_file.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
3358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/kill.h"
3458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process_metrics.h"
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(OS_LINUX)
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <sys/prctl.h>
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/ioctl.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_FREEBSD)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/event.h>
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/ucontext.h>
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <crt_externs.h>
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/event.h>
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern char** environ;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get the process's "environment" (i.e. the thing that setenv/getenv
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// work with).
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char** GetEnvironment() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *_NSGetEnviron();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return environ;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Set the process's "environment" (i.e. the thing that setenv/getenv
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// work with).
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetEnvironment(char** env) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *_NSGetEnviron() = env;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  environ = env;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Set the calling thread's signal mask to new_sigmask and return
863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// the previous signal mask.
873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochsigset_t SetSignalMask(const sigset_t& new_sigmask) {
883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  sigset_t old_sigmask;
893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#if defined(OS_ANDROID)
903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // POSIX says pthread_sigmask() must be used in multi-threaded processes,
913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // but Android's pthread_sigmask() was broken until 4.1:
923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // https://code.google.com/p/android/issues/detail?id=15337
933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // http://stackoverflow.com/questions/13777109/pthread-sigmask-on-android-not-working
943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  RAW_CHECK(sigprocmask(SIG_SETMASK, &new_sigmask, &old_sigmask) == 0);
953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#else
963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  RAW_CHECK(pthread_sigmask(SIG_SETMASK, &new_sigmask, &old_sigmask) == 0);
973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#endif
983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return old_sigmask;
993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_LINUX) || \
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__))
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResetChildSignalHandlersToDefaults() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The previous signal handlers are likely to be meaningless in the child's
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // context so we reset them to the defaults for now. http://crbug.com/44953
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These signal handlers are set up at least in browser_main_posix.cc:
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BrowserMainPartsPosix::PreEarlyInitialization and stack_trace_posix.cc:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EnableInProcessStackDumping.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGHUP, SIG_DFL);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGINT, SIG_DFL);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGILL, SIG_DFL);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGABRT, SIG_DFL);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGFPE, SIG_DFL);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGBUS, SIG_DFL);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGSEGV, SIG_DFL);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGSYS, SIG_DFL);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGTERM, SIG_DFL);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(jln): remove the Linux special case once kernels are fixed.
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Internally the kernel makes sigset_t an array of long large enough to have
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// one bit per signal.
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef uint64_t kernel_sigset_t;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is what struct sigaction looks like to the kernel at least on X86 and
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ARM. MIPS, for instance, is very different.
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct kernel_sigaction {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* k_sa_handler;  // For this usage it only needs to be a generic pointer.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned long k_sa_flags;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* k_sa_restorer;  // For this usage it only needs to be a generic pointer.
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kernel_sigset_t k_sa_mask;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// glibc's sigaction() will prevent access to sa_restorer, so we need to roll
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// our own.
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int sys_rt_sigaction(int sig, const struct kernel_sigaction* act,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     struct kernel_sigaction* oact) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return syscall(SYS_rt_sigaction, sig, act, oact, sizeof(kernel_sigset_t));
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This function is intended to be used in between fork() and execve() and will
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// reset all signal handlers to the default.
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The motivation for going through all of them is that sa_restorer can leak
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// from parents and help defeat ASLR on buggy kernels.  We reset it to NULL.
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// See crbug.com/177956.
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResetChildSignalHandlersToDefaults(void) {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int signum = 1; ; ++signum) {
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    struct kernel_sigaction act = {0};
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int sigaction_get_ret = sys_rt_sigaction(signum, NULL, &act);
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (sigaction_get_ret && errno == EINVAL) {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(NDEBUG)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Linux supports 32 real-time signals from 33 to 64.
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the number of signals in the Linux kernel changes, someone should
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // look at this code.
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const int kNumberOfSignals = 64;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RAW_CHECK(signum == kNumberOfSignals + 1);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // !defined(NDEBUG)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // All other failures are fatal.
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (sigaction_get_ret) {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RAW_LOG(FATAL, "sigaction (get) failed.");
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The kernel won't allow to re-set SIGKILL or SIGSTOP.
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (signum != SIGSTOP && signum != SIGKILL) {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      act.k_sa_handler = reinterpret_cast<void*>(SIG_DFL);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      act.k_sa_restorer = NULL;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (sys_rt_sigaction(signum, &act, NULL)) {
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        RAW_LOG(FATAL, "sigaction (set) failed.");
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(NDEBUG)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Now ask the kernel again and check that no restorer will leak.
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (sys_rt_sigaction(signum, NULL, &act) || act.k_sa_restorer) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RAW_LOG(FATAL, "Cound not fix sa_restorer.");
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // !defined(NDEBUG)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // !defined(OS_LINUX) ||
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__))
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Functor for |ScopedDIR| (below).
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct ScopedDIRClose {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void operator()(DIR* x) const {
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (x)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      closedir(x);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Automatically closes |DIR*|s.
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef scoped_ptr<DIR, ScopedDIRClose> ScopedDIR;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic const char kFDDir[] = "/proc/self/fd";
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic const char kFDDir[] = "/dev/fd";
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_SOLARIS)
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic const char kFDDir[] = "/dev/fd";
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_FREEBSD)
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic const char kFDDir[] = "/dev/fd";
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_OPENBSD)
2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic const char kFDDir[] = "/dev/fd";
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic const char kFDDir[] = "/proc/self/fd";
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // DANGER: no calls to malloc or locks are allowed from now on:
216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // http://crbug.com/36678
217b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
218b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Get the maximum number of FDs possible.
219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t max_fds = GetMaxFds();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
221b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DirReaderPosix fd_dir(kFDDir);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!fd_dir.IsValid()) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Fallback case: Try every possible fd.
224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    for (size_t i = 0; i < max_fds; ++i) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int fd = static_cast<int>(i);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Cannot use STL iterators here, since debug iterators use locks.
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size_t j;
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (j = 0; j < saved_mapping.size(); j++) {
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (fd == saved_mapping[j].dest)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (j < saved_mapping.size())
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Since we're just trying to close anything we can find,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ignore any error return values of close().
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      close(fd);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int dir_fd = fd_dir.fd();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for ( ; fd_dir.Next(); ) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Skip . and .. entries.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fd_dir.name()[0] == '.')
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *endptr;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errno = 0;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const long int fd = strtol(fd_dir.name(), &endptr, 10);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Cannot use STL iterators here, since debug iterators use locks.
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size_t i;
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (i = 0; i < saved_mapping.size(); i++) {
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (fd == saved_mapping[i].dest)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (i < saved_mapping.size())
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fd == dir_fd)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When running under Valgrind, Valgrind opens several FDs for its
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // own use and will complain if we try to close them.  All of
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // these FDs are >= |max_fds|, so we can check against that here
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before closing.  See https://bugs.kde.org/show_bug.cgi?id=191758
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fd < static_cast<int>(max_fds)) {
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      int ret = IGNORE_EINTR(close(fd));
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DPCHECK(ret == 0);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LaunchProcess(const std::vector<std::string>& argv,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const LaunchOptions& options,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   ProcessHandle* process_handle) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t fd_shuffle_size = 0;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (options.fds_to_remap) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fd_shuffle_size = options.fds_to_remap->size();
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InjectiveMultimap fd_shuffle1;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InjectiveMultimap fd_shuffle2;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd_shuffle1.reserve(fd_shuffle_size);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd_shuffle2.reserve(fd_shuffle_size);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<char*[]> new_environ;
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  char* const empty_environ = NULL;
29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  char* const* old_environ = GetEnvironment();
29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (options.clear_environ)
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    old_environ = &empty_environ;
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!options.environ.empty())
30046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    new_environ = AlterEnvironment(old_environ, options.environ);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  sigset_t full_sigset;
3033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  sigfillset(&full_sigset);
3043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const sigset_t orig_sigmask = SetSignalMask(full_sigset);
3053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pid_t pid;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (options.clone_flags) {
3093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // Signal handling in this function assumes the creation of a new
3103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // process, so we check that a thread is not being created by mistake
3113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // and that signal handling follows the process-creation rules.
3123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    RAW_CHECK(
3133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        !(options.clone_flags & (CLONE_SIGHAND | CLONE_THREAD | CLONE_VM)));
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pid = syscall(__NR_clone, options.clone_flags, 0, 0, 0);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pid = fork();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Always restore the original signal mask in the parent.
3223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (pid != 0) {
3233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    SetSignalMask(orig_sigmask);
3243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
3253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pid < 0) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DPLOG(ERROR) << "fork";
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (pid == 0) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Child process
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // DANGER: no calls to malloc or locks are allowed from now on:
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // http://crbug.com/36678
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // DANGER: fork() rule: in the child, if you don't end up doing exec*(),
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // you call _exit() instead of exit(). This is because _exit() does not
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // call any previously-registered (in the parent) exit handlers, which
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // might do things like block waiting for threads that don't even exist
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in the child.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If a child process uses the readline library, the process block forever.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In BSD like OSes including OS X it is safe to assign /dev/null as stdin.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See http://crbug.com/56596.
344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::ScopedFD null_fd(HANDLE_EINTR(open("/dev/null", O_RDONLY)));
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!null_fd.is_valid()) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RAW_LOG(ERROR, "Failed to open /dev/null");
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _exit(127);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int new_fd = HANDLE_EINTR(dup2(null_fd.get(), STDIN_FILENO));
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_fd != STDIN_FILENO) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RAW_LOG(ERROR, "Failed to dup /dev/null for stdin");
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _exit(127);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (options.new_process_group) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Instead of inheriting the process group ID of the parent, the child
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // starts off a new process group with pgid equal to its process ID.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (setpgid(0, 0) < 0) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RAW_LOG(ERROR, "setpgid failed");
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        _exit(127);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stop type-profiler.
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The profiler should be stopped between fork and exec since it inserts
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // locks at new/delete expressions.  See http://crbug.com/36678.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::type_profiler::Controller::Stop();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (options.maximize_rlimits) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Some resource limits need to be maximal in this child.
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (size_t i = 0; i < options.maximize_rlimits->size(); ++i) {
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const int resource = (*options.maximize_rlimits)[i];
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        struct rlimit limit;
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (getrlimit(resource, &limit) < 0) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          RAW_LOG(WARNING, "getrlimit failed");
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (limit.rlim_cur < limit.rlim_max) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          limit.rlim_cur = limit.rlim_max;
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          if (setrlimit(resource, &limit) < 0) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            RAW_LOG(WARNING, "setrlimit failed");
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RestoreDefaultExceptionHandler();
3886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (!options.replacement_bootstrap_name.empty())
3896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      ReplaceBootstrapPort(options.replacement_bootstrap_name);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResetChildSignalHandlersToDefaults();
3933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    SetSignalMask(orig_sigmask);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When debugging it can be helpful to check that we really aren't making
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // any hidden calls to malloc.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *malloc_thunk =
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(reinterpret_cast<void*>(malloc), 0xff, 8);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // 0
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (options.ctrl_terminal_fd >= 0) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Set process' controlling terminal.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (HANDLE_EINTR(setsid()) != -1) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (HANDLE_EINTR(
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set");
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RAW_LOG(WARNING, "setsid failed, ctrl terminal not set");
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_CHROMEOS)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (options.fds_to_remap) {
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Cannot use STL iterators here, since debug iterators use locks.
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (size_t i = 0; i < options.fds_to_remap->size(); ++i) {
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const FileHandleMappingVector::value_type& value =
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            (*options.fds_to_remap)[i];
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        fd_shuffle1.push_back(InjectionArc(value.first, value.second, false));
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        fd_shuffle2.push_back(InjectionArc(value.first, value.second, false));
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (!options.environ.empty() || options.clear_environ)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetEnvironment(new_environ.get());
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // fd_shuffle1 is mutated by this call because it cannot malloc.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ShuffleFileDescriptors(&fd_shuffle1))
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _exit(127);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseSuperfluousFds(fd_shuffle2);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
437c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Set NO_NEW_PRIVS by default. Since NO_NEW_PRIVS only exists in kernel
438c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // 3.5+, do not check the return value of prctl here.
439c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(OS_LINUX)
440c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#ifndef PR_SET_NO_NEW_PRIVS
441c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#define PR_SET_NO_NEW_PRIVS 38
442c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
443c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!options.allow_new_privs) {
4445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) && errno != EINVAL) {
4455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // Only log if the error is not EINVAL (i.e. not supported).
4465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        RAW_LOG(FATAL, "prctl(PR_SET_NO_NEW_PRIVS) failed");
447c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      }
448c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
449c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
450c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < argv.size(); i++)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      argv_cstr[i] = const_cast<char*>(argv[i].c_str());
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    argv_cstr[argv.size()] = NULL;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    execvp(argv_cstr[0], argv_cstr.get());
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_LOG(ERROR, "LaunchProcess: failed to execvp:");
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_LOG(ERROR, argv_cstr[0]);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    _exit(127);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Parent process
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (options.wait) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // While this isn't strictly disk IO, waiting for another process to
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // finish is the sort of thing ThreadRestrictions is trying to prevent.
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ThreadRestrictions::AssertIOAllowed();
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0));
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DPCHECK(ret > 0);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (process_handle)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *process_handle = pid;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LaunchProcess(const CommandLine& cmdline,
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const LaunchOptions& options,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   ProcessHandle* process_handle) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return LaunchProcess(cmdline.argv(), options, process_handle);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RaiseProcessToHighPriority() {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On POSIX, we don't actually do anything here.  We could try to nice() or
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // setpriority() or sched_getscheduler, but these all require extra rights.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return value used by GetAppOutputInternal to encapsulate the various exit
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scenarios from the function.
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum GetAppOutputInternalResult {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXECUTE_FAILURE,
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXECUTE_SUCCESS,
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOT_MAX_OUTPUT,
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Executes the application specified by |argv| and wait for it to exit. Stores
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the output (stdout) in |output|. If |do_search_path| is set, it searches the
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// path for the application; in that case, |envp| must be null, and it will use
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the current environment. If |do_search_path| is false, |argv[0]| should fully
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// specify the path of the application, and |envp| will be used as the
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// environment. Redirects stderr to /dev/null.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If we successfully start the application and get all requested output, we
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return GOT_MAX_OUTPUT, or if there is a problem starting or exiting
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the application we return RUN_FAILURE. Otherwise we return EXECUTE_SUCCESS.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The GOT_MAX_OUTPUT return value exists so a caller that asks for limited
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// output can treat this as a success, despite having an exit code of SIG_PIPE
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// due to us closing the output pipe.
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the case of EXECUTE_SUCCESS, the application exit code will be returned
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in |*exit_code|, which should be checked to determine if the application
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ran successfully.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GetAppOutputInternalResult GetAppOutputInternal(
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& argv,
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* const envp[],
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* output,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t max_output,
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool do_search_path,
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* exit_code) {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Doing a blocking wait for another command to finish counts as IO.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::AssertIOAllowed();
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exit_code must be supplied so calling function can determine success.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(exit_code);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *exit_code = EXIT_FAILURE;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pipe_fd[2];
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pid_t pid;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InjectiveMultimap fd_shuffle1, fd_shuffle2;
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd_shuffle1.reserve(3);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd_shuffle2.reserve(3);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Either |do_search_path| should be false or |envp| should be null, but not
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // both.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!do_search_path ^ !envp);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pipe(pipe_fd) < 0)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return EXECUTE_FAILURE;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (pid = fork()) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case -1:  // error
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close(pipe_fd[0]);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close(pipe_fd[1]);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return EXECUTE_FAILURE;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 0:  // child
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // DANGER: no calls to malloc or locks are allowed from now on:
5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // http://crbug.com/36678
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RestoreDefaultExceptionHandler();
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Obscure fork() rule: in the child, if you don't end up doing exec*(),
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // you call _exit() instead of exit(). This is because _exit() does not
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // call any previously-registered (in the parent) exit handlers, which
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // might do things like block waiting for threads that don't even exist
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // in the child.
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int dev_null = open("/dev/null", O_WRONLY);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (dev_null < 0)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          _exit(127);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Stop type-profiler.
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The profiler should be stopped between fork and exec since it inserts
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // locks at new/delete expressions.  See http://crbug.com/36678.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::type_profiler::Controller::Stop();
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true));
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Adding another element here? Remeber to increase the argument to
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // reserve(), above.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        for (size_t i = 0; i < fd_shuffle1.size(); ++i)
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          fd_shuffle2.push_back(fd_shuffle1[i]);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!ShuffleFileDescriptors(&fd_shuffle1))
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          _exit(127);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CloseSuperfluousFds(fd_shuffle2);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (size_t i = 0; i < argv.size(); i++)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          argv_cstr[i] = const_cast<char*>(argv[i].c_str());
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        argv_cstr[argv.size()] = NULL;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (do_search_path)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          execvp(argv_cstr[0], argv_cstr.get());
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          execve(argv_cstr[0], argv_cstr.get(), envp);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        _exit(127);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:  // parent
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Close our writing end of pipe now. Otherwise later read would not
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // be able to detect end of child's output (in theory we could still
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // write to the pipe).
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        close(pipe_fd[1]);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output->clear();
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char buffer[256];
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t output_buf_left = max_output;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssize_t bytes_read = 1;  // A lie to properly handle |max_output == 0|
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 // case in the logic below.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (output_buf_left > 0) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer,
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    std::min(output_buf_left, sizeof(buffer))));
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (bytes_read <= 0)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output->append(buffer, bytes_read);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output_buf_left -= static_cast<size_t>(bytes_read);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        close(pipe_fd[0]);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Always wait for exit code (even if we know we'll declare
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // GOT_MAX_OUTPUT).
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool success = WaitForExitCode(pid, exit_code);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If we stopped because we read as much as we wanted, we return
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // GOT_MAX_OUTPUT (because the child may exit due to |SIGPIPE|).
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!output_buf_left && bytes_read > 0)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return GOT_MAX_OUTPUT;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else if (success)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return EXECUTE_SUCCESS;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return EXECUTE_FAILURE;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetAppOutput(const CommandLine& cl, std::string* output) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetAppOutput(cl.argv(), output);
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run |execve()| with the current environment and store "unlimited" data.
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int exit_code;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetAppOutputInternalResult result = GetAppOutputInternal(
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      argv, NULL, output, std::numeric_limits<std::size_t>::max(), true,
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &exit_code);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(viettrungluu): Conceivably, we should have a timeout as well, so we
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// don't hang if what we're calling hangs.
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetAppOutputRestricted(const CommandLine& cl,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            std::string* output, size_t max_output) {
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run |execve()| with the empty environment.
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* const empty_environ = NULL;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int exit_code;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetAppOutputInternalResult result = GetAppOutputInternal(
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cl.argv(), &empty_environ, output, max_output, false, &exit_code);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result == GOT_MAX_OUTPUT || (result == EXECUTE_SUCCESS &&
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      exit_code == EXIT_SUCCESS);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetAppOutputWithExitCode(const CommandLine& cl,
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              std::string* output,
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int* exit_code) {
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run |execve()| with the current environment and store "unlimited" data.
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetAppOutputInternalResult result = GetAppOutputInternal(
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true,
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      exit_code);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result == EXECUTE_SUCCESS;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
665