process_util_posix.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <dirent.h>
6#include <errno.h>
7#include <fcntl.h>
8#include <signal.h>
9#include <stdlib.h>
10#include <sys/resource.h>
11#include <sys/time.h>
12#include <sys/types.h>
13#include <sys/wait.h>
14#include <unistd.h>
15
16#include <limits>
17#include <set>
18
19#include "base/command_line.h"
20#include "base/compiler_specific.h"
21#include "base/debug_util.h"
22#include "base/dir_reader_posix.h"
23#include "base/eintr_wrapper.h"
24#include "base/logging.h"
25#include "base/platform_thread.h"
26#include "base/process_util.h"
27#include "base/scoped_ptr.h"
28#include "base/stringprintf.h"
29#include "base/time.h"
30#include "base/waitable_event.h"
31
32#if defined(OS_MACOSX)
33#include <crt_externs.h>
34#define environ (*_NSGetEnviron())
35#else
36extern char** environ;
37#endif
38
39namespace base {
40
41namespace {
42
43int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds,
44                       bool* success) {
45  // This POSIX version of this function only guarantees that we wait no less
46  // than |wait_milliseconds| for the process to exit.  The child process may
47  // exit sometime before the timeout has ended but we may still block for up
48  // to 256 milliseconds after the fact.
49  //
50  // waitpid() has no direct support on POSIX for specifying a timeout, you can
51  // either ask it to block indefinitely or return immediately (WNOHANG).
52  // When a child process terminates a SIGCHLD signal is sent to the parent.
53  // Catching this signal would involve installing a signal handler which may
54  // affect other parts of the application and would be difficult to debug.
55  //
56  // Our strategy is to call waitpid() once up front to check if the process
57  // has already exited, otherwise to loop for wait_milliseconds, sleeping for
58  // at most 256 milliseconds each time using usleep() and then calling
59  // waitpid().  The amount of time we sleep starts out at 1 milliseconds, and
60  // we double it every 4 sleep cycles.
61  //
62  // usleep() is speced to exit if a signal is received for which a handler
63  // has been installed.  This means that when a SIGCHLD is sent, it will exit
64  // depending on behavior external to this function.
65  //
66  // This function is used primarily for unit tests, if we want to use it in
67  // the application itself it would probably be best to examine other routes.
68  int status = -1;
69  pid_t ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
70  static const int64 kMaxSleepInMicroseconds = 1 << 18;  // ~256 milliseconds.
71  int64 max_sleep_time_usecs = 1 << 10;  // ~1 milliseconds.
72  int64 double_sleep_time = 0;
73
74  // If the process hasn't exited yet, then sleep and try again.
75  Time wakeup_time = Time::Now() +
76      TimeDelta::FromMilliseconds(wait_milliseconds);
77  while (ret_pid == 0) {
78    Time now = Time::Now();
79    if (now > wakeup_time)
80      break;
81    // Guaranteed to be non-negative!
82    int64 sleep_time_usecs = (wakeup_time - now).InMicroseconds();
83    // Sleep for a bit while we wait for the process to finish.
84    if (sleep_time_usecs > max_sleep_time_usecs)
85      sleep_time_usecs = max_sleep_time_usecs;
86
87    // usleep() will return 0 and set errno to EINTR on receipt of a signal
88    // such as SIGCHLD.
89    usleep(sleep_time_usecs);
90    ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
91
92    if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) &&
93        (double_sleep_time++ % 4 == 0)) {
94      max_sleep_time_usecs *= 2;
95    }
96  }
97
98  if (success)
99    *success = (ret_pid != -1);
100
101  return status;
102}
103
104void StackDumpSignalHandler(int signal) {
105  LOG(ERROR) << "Received signal " << signal;
106  StackTrace().PrintBacktrace();
107  _exit(1);
108}
109
110void ResetChildSignalHandlersToDefaults() {
111  // The previous signal handlers are likely to be meaningless in the child's
112  // context so we reset them to the defaults for now. http://crbug.com/44953
113  // These signal handlers are setup in browser_main.cc:BrowserMain
114  signal(SIGTERM, SIG_DFL);
115  signal(SIGHUP, SIG_DFL);
116  signal(SIGINT, SIG_DFL);
117}
118
119}  // anonymous namespace
120
121ProcessId GetCurrentProcId() {
122  return getpid();
123}
124
125ProcessHandle GetCurrentProcessHandle() {
126  return GetCurrentProcId();
127}
128
129bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
130  // On Posix platforms, process handles are the same as PIDs, so we
131  // don't need to do anything.
132  *handle = pid;
133  return true;
134}
135
136bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) {
137  // On POSIX permissions are checked for each operation on process,
138  // not when opening a "handle".
139  return OpenProcessHandle(pid, handle);
140}
141
142void CloseProcessHandle(ProcessHandle process) {
143  // See OpenProcessHandle, nothing to do.
144  return;
145}
146
147ProcessId GetProcId(ProcessHandle process) {
148  return process;
149}
150
151// Attempts to kill the process identified by the given process
152// entry structure.  Ignores specified exit_code; posix can't force that.
153// Returns true if this is successful, false otherwise.
154bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) {
155  DCHECK_GT(process_id, 1) << " tried to kill invalid process_id";
156  if (process_id <= 1)
157    return false;
158  static unsigned kMaxSleepMs = 1000;
159  unsigned sleep_ms = 4;
160
161  bool result = kill(process_id, SIGTERM) == 0;
162
163  if (result && wait) {
164    int tries = 60;
165    // The process may not end immediately due to pending I/O
166    bool exited = false;
167    while (tries-- > 0) {
168      pid_t pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG));
169      if (pid == process_id) {
170        exited = true;
171        break;
172      }
173      if (pid == -1) {
174        if (errno == ECHILD) {
175          // The wait may fail with ECHILD if another process also waited for
176          // the same pid, causing the process state to get cleaned up.
177          exited = true;
178          break;
179        }
180        DPLOG(ERROR) << "Error waiting for process " << process_id;
181      }
182
183      usleep(sleep_ms * 1000);
184      if (sleep_ms < kMaxSleepMs)
185        sleep_ms *= 2;
186    }
187
188    if (!exited)
189      result = kill(process_id, SIGKILL) == 0;
190  }
191
192  if (!result)
193    DPLOG(ERROR) << "Unable to terminate process " << process_id;
194
195  return result;
196}
197
198bool KillProcessGroup(ProcessHandle process_group_id) {
199  bool result = kill(-1 * process_group_id, SIGKILL) == 0;
200  if (!result)
201    PLOG(ERROR) << "Unable to terminate process group " << process_group_id;
202  return result;
203}
204
205// A class to handle auto-closing of DIR*'s.
206class ScopedDIRClose {
207 public:
208  inline void operator()(DIR* x) const {
209    if (x) {
210      closedir(x);
211    }
212  }
213};
214typedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR;
215
216#if defined(OS_LINUX)
217  static const rlim_t kSystemDefaultMaxFds = 8192;
218  static const char kFDDir[] = "/proc/self/fd";
219#elif defined(OS_MACOSX)
220  static const rlim_t kSystemDefaultMaxFds = 256;
221  static const char kFDDir[] = "/dev/fd";
222#elif defined(OS_SOLARIS)
223  static const rlim_t kSystemDefaultMaxFds = 8192;
224  static const char kFDDir[] = "/dev/fd";
225#elif defined(OS_FREEBSD)
226  static const rlim_t kSystemDefaultMaxFds = 8192;
227  static const char kFDDir[] = "/dev/fd";
228#elif defined(OS_OPENBSD)
229  static const rlim_t kSystemDefaultMaxFds = 256;
230  static const char kFDDir[] = "/dev/fd";
231#endif
232
233void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
234  // DANGER: no calls to malloc are allowed from now on:
235  // http://crbug.com/36678
236
237  // Get the maximum number of FDs possible.
238  struct rlimit nofile;
239  rlim_t max_fds;
240  if (getrlimit(RLIMIT_NOFILE, &nofile)) {
241    // getrlimit failed. Take a best guess.
242    max_fds = kSystemDefaultMaxFds;
243    DLOG(ERROR) << "getrlimit(RLIMIT_NOFILE) failed: " << errno;
244  } else {
245    max_fds = nofile.rlim_cur;
246  }
247
248  if (max_fds > INT_MAX)
249    max_fds = INT_MAX;
250
251  DirReaderPosix fd_dir(kFDDir);
252
253  if (!fd_dir.IsValid()) {
254    // Fallback case: Try every possible fd.
255    for (rlim_t i = 0; i < max_fds; ++i) {
256      const int fd = static_cast<int>(i);
257      if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
258        continue;
259      InjectiveMultimap::const_iterator j;
260      for (j = saved_mapping.begin(); j != saved_mapping.end(); j++) {
261        if (fd == j->dest)
262          break;
263      }
264      if (j != saved_mapping.end())
265        continue;
266
267      // Since we're just trying to close anything we can find,
268      // ignore any error return values of close().
269      int unused ALLOW_UNUSED = HANDLE_EINTR(close(fd));
270    }
271    return;
272  }
273
274  const int dir_fd = fd_dir.fd();
275
276  for ( ; fd_dir.Next(); ) {
277    // Skip . and .. entries.
278    if (fd_dir.name()[0] == '.')
279      continue;
280
281    char *endptr;
282    errno = 0;
283    const long int fd = strtol(fd_dir.name(), &endptr, 10);
284    if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno)
285      continue;
286    if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
287      continue;
288    InjectiveMultimap::const_iterator i;
289    for (i = saved_mapping.begin(); i != saved_mapping.end(); i++) {
290      if (fd == i->dest)
291        break;
292    }
293    if (i != saved_mapping.end())
294      continue;
295    if (fd == dir_fd)
296      continue;
297
298    // When running under Valgrind, Valgrind opens several FDs for its
299    // own use and will complain if we try to close them.  All of
300    // these FDs are >= |max_fds|, so we can check against that here
301    // before closing.  See https://bugs.kde.org/show_bug.cgi?id=191758
302    if (fd < static_cast<int>(max_fds)) {
303      int ret = HANDLE_EINTR(close(fd));
304      DPCHECK(ret == 0);
305    }
306  }
307}
308
309char** AlterEnvironment(const environment_vector& changes,
310                        const char* const* const env) {
311  unsigned count = 0;
312  unsigned size = 0;
313
314  // First assume that all of the current environment will be included.
315  for (unsigned i = 0; env[i]; i++) {
316    const char *const pair = env[i];
317    count++;
318    size += strlen(pair) + 1 /* terminating NUL */;
319  }
320
321  for (environment_vector::const_iterator
322       j = changes.begin(); j != changes.end(); j++) {
323    bool found = false;
324    const char *pair;
325
326    for (unsigned i = 0; env[i]; i++) {
327      pair = env[i];
328      const char *const equals = strchr(pair, '=');
329      if (!equals)
330        continue;
331      const unsigned keylen = equals - pair;
332      if (keylen == j->first.size() &&
333          memcmp(pair, j->first.data(), keylen) == 0) {
334        found = true;
335        break;
336      }
337    }
338
339    // if found, we'll either be deleting or replacing this element.
340    if (found) {
341      count--;
342      size -= strlen(pair) + 1;
343      if (j->second.size())
344        found = false;
345    }
346
347    // if !found, then we have a new element to add.
348    if (!found && j->second.size() > 0) {
349      count++;
350      size += j->first.size() + 1 /* '=' */ + j->second.size() + 1 /* NUL */;
351    }
352  }
353
354  count++;  // for the final NULL
355  uint8_t *buffer = new uint8_t[sizeof(char*) * count + size];
356  char **const ret = reinterpret_cast<char**>(buffer);
357  unsigned k = 0;
358  char *scratch = reinterpret_cast<char*>(buffer + sizeof(char*) * count);
359
360  for (unsigned i = 0; env[i]; i++) {
361    const char *const pair = env[i];
362    const char *const equals = strchr(pair, '=');
363    if (!equals) {
364      const unsigned len = strlen(pair);
365      ret[k++] = scratch;
366      memcpy(scratch, pair, len + 1);
367      scratch += len + 1;
368      continue;
369    }
370    const unsigned keylen = equals - pair;
371    bool handled = false;
372    for (environment_vector::const_iterator
373         j = changes.begin(); j != changes.end(); j++) {
374      if (j->first.size() == keylen &&
375          memcmp(j->first.data(), pair, keylen) == 0) {
376        if (!j->second.empty()) {
377          ret[k++] = scratch;
378          memcpy(scratch, pair, keylen + 1);
379          scratch += keylen + 1;
380          memcpy(scratch, j->second.c_str(), j->second.size() + 1);
381          scratch += j->second.size() + 1;
382        }
383        handled = true;
384        break;
385      }
386    }
387
388    if (!handled) {
389      const unsigned len = strlen(pair);
390      ret[k++] = scratch;
391      memcpy(scratch, pair, len + 1);
392      scratch += len + 1;
393    }
394  }
395
396  // Now handle new elements
397  for (environment_vector::const_iterator
398       j = changes.begin(); j != changes.end(); j++) {
399    if (j->second.size() == 0)
400      continue;
401
402    bool found = false;
403    for (unsigned i = 0; env[i]; i++) {
404      const char *const pair = env[i];
405      const char *const equals = strchr(pair, '=');
406      if (!equals)
407        continue;
408      const unsigned keylen = equals - pair;
409      if (keylen == j->first.size() &&
410          memcmp(pair, j->first.data(), keylen) == 0) {
411        found = true;
412        break;
413      }
414    }
415
416    if (!found) {
417      ret[k++] = scratch;
418      memcpy(scratch, j->first.data(), j->first.size());
419      scratch += j->first.size();
420      *scratch++ = '=';
421      memcpy(scratch, j->second.c_str(), j->second.size() + 1);
422      scratch += j->second.size() + 1;
423     }
424  }
425
426  ret[k] = NULL;
427  return ret;
428}
429
430bool LaunchAppImpl(
431    const std::vector<std::string>& argv,
432    const environment_vector& env_changes,
433    const file_handle_mapping_vector& fds_to_remap,
434    bool wait,
435    ProcessHandle* process_handle,
436    bool start_new_process_group) {
437  pid_t pid;
438  InjectiveMultimap fd_shuffle1, fd_shuffle2;
439  fd_shuffle1.reserve(fds_to_remap.size());
440  fd_shuffle2.reserve(fds_to_remap.size());
441  scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
442  scoped_array<char*> new_environ(AlterEnvironment(env_changes, environ));
443
444  pid = fork();
445  if (pid < 0)
446    return false;
447
448  if (pid == 0) {
449    // Child process
450
451    if (start_new_process_group) {
452      // Instead of inheriting the process group ID of the parent, the child
453      // starts off a new process group with pgid equal to its process ID.
454      if (setpgid(0, 0) < 0)
455        return false;
456    }
457#if defined(OS_MACOSX)
458    RestoreDefaultExceptionHandler();
459#endif
460
461    ResetChildSignalHandlersToDefaults();
462
463#if 0
464    // When debugging it can be helpful to check that we really aren't making
465    // any hidden calls to malloc.
466    void *malloc_thunk =
467        reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095);
468    mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
469    memset(reinterpret_cast<void*>(malloc), 0xff, 8);
470#endif
471
472    // DANGER: no calls to malloc are allowed from now on:
473    // http://crbug.com/36678
474
475    for (file_handle_mapping_vector::const_iterator
476        it = fds_to_remap.begin(); it != fds_to_remap.end(); ++it) {
477      fd_shuffle1.push_back(InjectionArc(it->first, it->second, false));
478      fd_shuffle2.push_back(InjectionArc(it->first, it->second, false));
479    }
480
481    environ = new_environ.get();
482
483    // Obscure fork() rule: in the child, if you don't end up doing exec*(),
484    // you call _exit() instead of exit(). This is because _exit() does not
485    // call any previously-registered (in the parent) exit handlers, which
486    // might do things like block waiting for threads that don't even exist
487    // in the child.
488
489    // fd_shuffle1 is mutated by this call because it cannot malloc.
490    if (!ShuffleFileDescriptors(&fd_shuffle1))
491      _exit(127);
492
493    CloseSuperfluousFds(fd_shuffle2);
494
495    for (size_t i = 0; i < argv.size(); i++)
496      argv_cstr[i] = const_cast<char*>(argv[i].c_str());
497    argv_cstr[argv.size()] = NULL;
498    execvp(argv_cstr[0], argv_cstr.get());
499    RAW_LOG(ERROR, "LaunchApp: failed to execvp:");
500    RAW_LOG(ERROR, argv_cstr[0]);
501    _exit(127);
502  } else {
503    // Parent process
504    if (wait) {
505      pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0));
506      DPCHECK(ret > 0);
507    }
508
509    if (process_handle)
510      *process_handle = pid;
511  }
512
513  return true;
514}
515
516bool LaunchApp(
517    const std::vector<std::string>& argv,
518    const environment_vector& env_changes,
519    const file_handle_mapping_vector& fds_to_remap,
520    bool wait,
521    ProcessHandle* process_handle) {
522  return LaunchAppImpl(argv, env_changes, fds_to_remap,
523                       wait, process_handle, false);
524}
525
526bool LaunchAppInNewProcessGroup(
527    const std::vector<std::string>& argv,
528    const environment_vector& env_changes,
529    const file_handle_mapping_vector& fds_to_remap,
530    bool wait,
531    ProcessHandle* process_handle) {
532  return LaunchAppImpl(argv, env_changes, fds_to_remap, wait,
533                       process_handle, true);
534}
535
536bool LaunchApp(const std::vector<std::string>& argv,
537               const file_handle_mapping_vector& fds_to_remap,
538               bool wait, ProcessHandle* process_handle) {
539  base::environment_vector no_env;
540  return LaunchApp(argv, no_env, fds_to_remap, wait, process_handle);
541}
542
543bool LaunchApp(const CommandLine& cl,
544               bool wait, bool start_hidden,
545               ProcessHandle* process_handle) {
546  file_handle_mapping_vector no_files;
547  return LaunchApp(cl.argv(), no_files, wait, process_handle);
548}
549
550ProcessMetrics::~ProcessMetrics() { }
551
552void EnableTerminationOnHeapCorruption() {
553  // On POSIX, there nothing to do AFAIK.
554}
555
556bool EnableInProcessStackDumping() {
557  // When running in an application, our code typically expects SIGPIPE
558  // to be ignored.  Therefore, when testing that same code, it should run
559  // with SIGPIPE ignored as well.
560  struct sigaction action;
561  action.sa_handler = SIG_IGN;
562  action.sa_flags = 0;
563  sigemptyset(&action.sa_mask);
564  bool success = (sigaction(SIGPIPE, &action, NULL) == 0);
565
566  success &= (signal(SIGILL, &StackDumpSignalHandler) != SIG_ERR);
567  success &= (signal(SIGABRT, &StackDumpSignalHandler) != SIG_ERR);
568  success &= (signal(SIGFPE, &StackDumpSignalHandler) != SIG_ERR);
569  success &= (signal(SIGBUS, &StackDumpSignalHandler) != SIG_ERR);
570  success &= (signal(SIGSEGV, &StackDumpSignalHandler) != SIG_ERR);
571  success &= (signal(SIGSYS, &StackDumpSignalHandler) != SIG_ERR);
572
573  return success;
574}
575
576void AttachToConsole() {
577  // On POSIX, there nothing to do AFAIK. Maybe create a new console if none
578  // exist?
579}
580
581void RaiseProcessToHighPriority() {
582  // On POSIX, we don't actually do anything here.  We could try to nice() or
583  // setpriority() or sched_getscheduler, but these all require extra rights.
584}
585
586bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
587  int status;
588  const pid_t result = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
589  if (result == -1) {
590    PLOG(ERROR) << "waitpid(" << handle << ")";
591    if (child_exited)
592      *child_exited = false;
593    return false;
594  } else if (result == 0) {
595    // the child hasn't exited yet.
596    if (child_exited)
597      *child_exited = false;
598    return false;
599  }
600
601  if (child_exited)
602    *child_exited = true;
603
604  if (WIFSIGNALED(status)) {
605    switch (WTERMSIG(status)) {
606      case SIGSEGV:
607      case SIGILL:
608      case SIGABRT:
609      case SIGFPE:
610        return true;
611      default:
612        return false;
613    }
614  }
615
616  if (WIFEXITED(status))
617    return WEXITSTATUS(status) != 0;
618
619  return false;
620}
621
622bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
623  int status;
624  if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) {
625    NOTREACHED();
626    return false;
627  }
628
629  if (WIFEXITED(status)) {
630    *exit_code = WEXITSTATUS(status);
631    return true;
632  }
633
634  // If it didn't exit cleanly, it must have been signaled.
635  DCHECK(WIFSIGNALED(status));
636  return false;
637}
638
639bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code,
640                                int64 timeout_milliseconds) {
641  bool waitpid_success = false;
642  int status = WaitpidWithTimeout(handle, timeout_milliseconds,
643                                  &waitpid_success);
644  if (status == -1)
645    return false;
646  if (!waitpid_success)
647    return false;
648  if (!WIFEXITED(status))
649    return false;
650  if (WIFSIGNALED(status)) {
651    *exit_code = -1;
652    return true;
653  }
654  *exit_code = WEXITSTATUS(status);
655  return true;
656}
657
658bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) {
659  bool waitpid_success;
660  int status;
661  if (wait_milliseconds == base::kNoTimeout)
662    waitpid_success = (HANDLE_EINTR(waitpid(handle, &status, 0)) != -1);
663  else
664    status = WaitpidWithTimeout(handle, wait_milliseconds, &waitpid_success);
665  if (status != -1) {
666    DCHECK(waitpid_success);
667    return WIFEXITED(status);
668  } else {
669    return false;
670  }
671}
672
673bool CrashAwareSleep(ProcessHandle handle, int64 wait_milliseconds) {
674  bool waitpid_success;
675  int status = WaitpidWithTimeout(handle, wait_milliseconds, &waitpid_success);
676  if (status != -1) {
677    DCHECK(waitpid_success);
678    return !(WIFEXITED(status) || WIFSIGNALED(status));
679  } else {
680    // If waitpid returned with an error, then the process doesn't exist
681    // (which most probably means it didn't exist before our call).
682    return waitpid_success;
683  }
684}
685
686int64 TimeValToMicroseconds(const struct timeval& tv) {
687  static const int kMicrosecondsPerSecond = 1000000;
688  int64 ret = tv.tv_sec;  // Avoid (int * int) integer overflow.
689  ret *= kMicrosecondsPerSecond;
690  ret += tv.tv_usec;
691  return ret;
692}
693
694// Executes the application specified by |cl| and wait for it to exit. Stores
695// the output (stdout) in |output|. If |do_search_path| is set, it searches the
696// path for the application; in that case, |envp| must be null, and it will use
697// the current environment. If |do_search_path| is false, |cl| should fully
698// specify the path of the application, and |envp| will be used as the
699// environment. Redirects stderr to /dev/null. Returns true on success
700// (application launched and exited cleanly, with exit code indicating success).
701static bool GetAppOutputInternal(const CommandLine& cl, char* const envp[],
702                                 std::string* output, size_t max_output,
703                                 bool do_search_path) {
704  int pipe_fd[2];
705  pid_t pid;
706  InjectiveMultimap fd_shuffle1, fd_shuffle2;
707  const std::vector<std::string>& argv = cl.argv();
708  scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
709
710  fd_shuffle1.reserve(3);
711  fd_shuffle2.reserve(3);
712
713  // Either |do_search_path| should be false or |envp| should be null, but not
714  // both.
715  DCHECK(!do_search_path ^ !envp);
716
717  if (pipe(pipe_fd) < 0)
718    return false;
719
720  switch (pid = fork()) {
721    case -1:  // error
722      close(pipe_fd[0]);
723      close(pipe_fd[1]);
724      return false;
725    case 0:  // child
726      {
727#if defined(OS_MACOSX)
728        RestoreDefaultExceptionHandler();
729#endif
730        // DANGER: no calls to malloc are allowed from now on:
731        // http://crbug.com/36678
732
733        // Obscure fork() rule: in the child, if you don't end up doing exec*(),
734        // you call _exit() instead of exit(). This is because _exit() does not
735        // call any previously-registered (in the parent) exit handlers, which
736        // might do things like block waiting for threads that don't even exist
737        // in the child.
738        int dev_null = open("/dev/null", O_WRONLY);
739        if (dev_null < 0)
740          _exit(127);
741
742        fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
743        fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true));
744        fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
745        // Adding another element here? Remeber to increase the argument to
746        // reserve(), above.
747
748        std::copy(fd_shuffle1.begin(), fd_shuffle1.end(),
749                  std::back_inserter(fd_shuffle2));
750
751        if (!ShuffleFileDescriptors(&fd_shuffle1))
752          _exit(127);
753
754        CloseSuperfluousFds(fd_shuffle2);
755
756        for (size_t i = 0; i < argv.size(); i++)
757          argv_cstr[i] = const_cast<char*>(argv[i].c_str());
758        argv_cstr[argv.size()] = NULL;
759        if (do_search_path)
760          execvp(argv_cstr[0], argv_cstr.get());
761        else
762          execve(argv_cstr[0], argv_cstr.get(), envp);
763        _exit(127);
764      }
765    default:  // parent
766      {
767        // Close our writing end of pipe now. Otherwise later read would not
768        // be able to detect end of child's output (in theory we could still
769        // write to the pipe).
770        close(pipe_fd[1]);
771
772        output->clear();
773        char buffer[256];
774        size_t output_buf_left = max_output;
775        ssize_t bytes_read = 1;  // A lie to properly handle |max_output == 0|
776                                 // case in the logic below.
777
778        while (output_buf_left > 0) {
779          bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer,
780                                    std::min(output_buf_left, sizeof(buffer))));
781          if (bytes_read <= 0)
782            break;
783          output->append(buffer, bytes_read);
784          output_buf_left -= static_cast<size_t>(bytes_read);
785        }
786        close(pipe_fd[0]);
787
788        // Always wait for exit code (even if we know we'll declare success).
789        int exit_code = EXIT_FAILURE;
790        bool success = WaitForExitCode(pid, &exit_code);
791
792        // If we stopped because we read as much as we wanted, we always declare
793        // success (because the child may exit due to |SIGPIPE|).
794        if (output_buf_left || bytes_read <= 0) {
795          if (!success || exit_code != EXIT_SUCCESS)
796            return false;
797        }
798
799        return true;
800      }
801  }
802}
803
804bool GetAppOutput(const CommandLine& cl, std::string* output) {
805  // Run |execve()| with the current environment and store "unlimited" data.
806  return GetAppOutputInternal(cl, NULL, output,
807                              std::numeric_limits<std::size_t>::max(), true);
808}
809
810// TODO(viettrungluu): Conceivably, we should have a timeout as well, so we
811// don't hang if what we're calling hangs.
812bool GetAppOutputRestricted(const CommandLine& cl,
813                            std::string* output, size_t max_output) {
814  // Run |execve()| with the empty environment.
815  char* const empty_environ = NULL;
816  return GetAppOutputInternal(cl, &empty_environ, output, max_output, false);
817}
818
819bool WaitForProcessesToExit(const std::wstring& executable_name,
820                            int64 wait_milliseconds,
821                            const ProcessFilter* filter) {
822  bool result = false;
823
824  // TODO(port): This is inefficient, but works if there are multiple procs.
825  // TODO(port): use waitpid to avoid leaving zombies around
826
827  base::Time end_time = base::Time::Now() +
828      base::TimeDelta::FromMilliseconds(wait_milliseconds);
829  do {
830    NamedProcessIterator iter(executable_name, filter);
831    if (!iter.NextProcessEntry()) {
832      result = true;
833      break;
834    }
835    PlatformThread::Sleep(100);
836  } while ((base::Time::Now() - end_time) > base::TimeDelta());
837
838  return result;
839}
840
841bool CleanupProcesses(const std::wstring& executable_name,
842                      int64 wait_milliseconds,
843                      int exit_code,
844                      const ProcessFilter* filter) {
845  bool exited_cleanly =
846      WaitForProcessesToExit(executable_name, wait_milliseconds,
847                             filter);
848  if (!exited_cleanly)
849    KillProcesses(executable_name, exit_code, filter);
850  return exited_cleanly;
851}
852
853}  // namespace base
854