launch_posix.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
1// Copyright (c) 2012 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 "base/process/launch.h" 6 7#include <dirent.h> 8#include <errno.h> 9#include <fcntl.h> 10#include <signal.h> 11#include <stdlib.h> 12#include <sys/resource.h> 13#include <sys/time.h> 14#include <sys/types.h> 15#include <sys/wait.h> 16#include <unistd.h> 17 18#include <iterator> 19#include <limits> 20#include <set> 21 22#include "base/allocator/type_profiler_control.h" 23#include "base/command_line.h" 24#include "base/compiler_specific.h" 25#include "base/debug/debugger.h" 26#include "base/debug/stack_trace.h" 27#include "base/file_util.h" 28#include "base/files/dir_reader_posix.h" 29#include "base/files/scoped_file.h" 30#include "base/logging.h" 31#include "base/memory/scoped_ptr.h" 32#include "base/posix/eintr_wrapper.h" 33#include "base/process/kill.h" 34#include "base/process/process_metrics.h" 35#include "base/strings/stringprintf.h" 36#include "base/synchronization/waitable_event.h" 37#include "base/third_party/dynamic_annotations/dynamic_annotations.h" 38#include "base/threading/platform_thread.h" 39#include "base/threading/thread_restrictions.h" 40 41#if defined(OS_LINUX) 42#include <sys/prctl.h> 43#endif 44 45#if defined(OS_CHROMEOS) 46#include <sys/ioctl.h> 47#endif 48 49#if defined(OS_FREEBSD) 50#include <sys/event.h> 51#include <sys/ucontext.h> 52#endif 53 54#if defined(OS_MACOSX) 55#include <crt_externs.h> 56#include <sys/event.h> 57#else 58extern char** environ; 59#endif 60 61namespace base { 62 63namespace { 64 65// Get the process's "environment" (i.e. the thing that setenv/getenv 66// work with). 67char** GetEnvironment() { 68#if defined(OS_MACOSX) 69 return *_NSGetEnviron(); 70#else 71 return environ; 72#endif 73} 74 75// Set the process's "environment" (i.e. the thing that setenv/getenv 76// work with). 77void SetEnvironment(char** env) { 78#if defined(OS_MACOSX) 79 *_NSGetEnviron() = env; 80#else 81 environ = env; 82#endif 83} 84 85// Set the calling thread's signal mask to new_sigmask and return 86// the previous signal mask. 87sigset_t SetSignalMask(const sigset_t& new_sigmask) { 88 sigset_t old_sigmask; 89#if defined(OS_ANDROID) 90 // POSIX says pthread_sigmask() must be used in multi-threaded processes, 91 // but Android's pthread_sigmask() was broken until 4.1: 92 // https://code.google.com/p/android/issues/detail?id=15337 93 // http://stackoverflow.com/questions/13777109/pthread-sigmask-on-android-not-working 94 RAW_CHECK(sigprocmask(SIG_SETMASK, &new_sigmask, &old_sigmask) == 0); 95#else 96 RAW_CHECK(pthread_sigmask(SIG_SETMASK, &new_sigmask, &old_sigmask) == 0); 97#endif 98 return old_sigmask; 99} 100 101#if !defined(OS_LINUX) || \ 102 (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) 103void ResetChildSignalHandlersToDefaults() { 104 // The previous signal handlers are likely to be meaningless in the child's 105 // context so we reset them to the defaults for now. http://crbug.com/44953 106 // These signal handlers are set up at least in browser_main_posix.cc: 107 // BrowserMainPartsPosix::PreEarlyInitialization and stack_trace_posix.cc: 108 // EnableInProcessStackDumping. 109 signal(SIGHUP, SIG_DFL); 110 signal(SIGINT, SIG_DFL); 111 signal(SIGILL, SIG_DFL); 112 signal(SIGABRT, SIG_DFL); 113 signal(SIGFPE, SIG_DFL); 114 signal(SIGBUS, SIG_DFL); 115 signal(SIGSEGV, SIG_DFL); 116 signal(SIGSYS, SIG_DFL); 117 signal(SIGTERM, SIG_DFL); 118} 119 120#else 121 122// TODO(jln): remove the Linux special case once kernels are fixed. 123 124// Internally the kernel makes sigset_t an array of long large enough to have 125// one bit per signal. 126typedef uint64_t kernel_sigset_t; 127 128// This is what struct sigaction looks like to the kernel at least on X86 and 129// ARM. MIPS, for instance, is very different. 130struct kernel_sigaction { 131 void* k_sa_handler; // For this usage it only needs to be a generic pointer. 132 unsigned long k_sa_flags; 133 void* k_sa_restorer; // For this usage it only needs to be a generic pointer. 134 kernel_sigset_t k_sa_mask; 135}; 136 137// glibc's sigaction() will prevent access to sa_restorer, so we need to roll 138// our own. 139int sys_rt_sigaction(int sig, const struct kernel_sigaction* act, 140 struct kernel_sigaction* oact) { 141 return syscall(SYS_rt_sigaction, sig, act, oact, sizeof(kernel_sigset_t)); 142} 143 144// This function is intended to be used in between fork() and execve() and will 145// reset all signal handlers to the default. 146// The motivation for going through all of them is that sa_restorer can leak 147// from parents and help defeat ASLR on buggy kernels. We reset it to NULL. 148// See crbug.com/177956. 149void ResetChildSignalHandlersToDefaults(void) { 150 for (int signum = 1; ; ++signum) { 151 struct kernel_sigaction act = {0}; 152 int sigaction_get_ret = sys_rt_sigaction(signum, NULL, &act); 153 if (sigaction_get_ret && errno == EINVAL) { 154#if !defined(NDEBUG) 155 // Linux supports 32 real-time signals from 33 to 64. 156 // If the number of signals in the Linux kernel changes, someone should 157 // look at this code. 158 const int kNumberOfSignals = 64; 159 RAW_CHECK(signum == kNumberOfSignals + 1); 160#endif // !defined(NDEBUG) 161 break; 162 } 163 // All other failures are fatal. 164 if (sigaction_get_ret) { 165 RAW_LOG(FATAL, "sigaction (get) failed."); 166 } 167 168 // The kernel won't allow to re-set SIGKILL or SIGSTOP. 169 if (signum != SIGSTOP && signum != SIGKILL) { 170 act.k_sa_handler = reinterpret_cast<void*>(SIG_DFL); 171 act.k_sa_restorer = NULL; 172 if (sys_rt_sigaction(signum, &act, NULL)) { 173 RAW_LOG(FATAL, "sigaction (set) failed."); 174 } 175 } 176#if !defined(NDEBUG) 177 // Now ask the kernel again and check that no restorer will leak. 178 if (sys_rt_sigaction(signum, NULL, &act) || act.k_sa_restorer) { 179 RAW_LOG(FATAL, "Cound not fix sa_restorer."); 180 } 181#endif // !defined(NDEBUG) 182 } 183} 184#endif // !defined(OS_LINUX) || 185 // (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) 186 187} // anonymous namespace 188 189// Functor for |ScopedDIR| (below). 190struct ScopedDIRClose { 191 inline void operator()(DIR* x) const { 192 if (x) 193 closedir(x); 194 } 195}; 196 197// Automatically closes |DIR*|s. 198typedef scoped_ptr<DIR, ScopedDIRClose> ScopedDIR; 199 200#if defined(OS_LINUX) 201static const char kFDDir[] = "/proc/self/fd"; 202#elif defined(OS_MACOSX) 203static const char kFDDir[] = "/dev/fd"; 204#elif defined(OS_SOLARIS) 205static const char kFDDir[] = "/dev/fd"; 206#elif defined(OS_FREEBSD) 207static const char kFDDir[] = "/dev/fd"; 208#elif defined(OS_OPENBSD) 209static const char kFDDir[] = "/dev/fd"; 210#elif defined(OS_ANDROID) 211static const char kFDDir[] = "/proc/self/fd"; 212#endif 213 214void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) { 215 // DANGER: no calls to malloc or locks are allowed from now on: 216 // http://crbug.com/36678 217 218 // Get the maximum number of FDs possible. 219 size_t max_fds = GetMaxFds(); 220 221 DirReaderPosix fd_dir(kFDDir); 222 if (!fd_dir.IsValid()) { 223 // Fallback case: Try every possible fd. 224 for (size_t i = 0; i < max_fds; ++i) { 225 const int fd = static_cast<int>(i); 226 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) 227 continue; 228 // Cannot use STL iterators here, since debug iterators use locks. 229 size_t j; 230 for (j = 0; j < saved_mapping.size(); j++) { 231 if (fd == saved_mapping[j].dest) 232 break; 233 } 234 if (j < saved_mapping.size()) 235 continue; 236 237 // Since we're just trying to close anything we can find, 238 // ignore any error return values of close(). 239 close(fd); 240 } 241 return; 242 } 243 244 const int dir_fd = fd_dir.fd(); 245 246 for ( ; fd_dir.Next(); ) { 247 // Skip . and .. entries. 248 if (fd_dir.name()[0] == '.') 249 continue; 250 251 char *endptr; 252 errno = 0; 253 const long int fd = strtol(fd_dir.name(), &endptr, 10); 254 if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno) 255 continue; 256 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) 257 continue; 258 // Cannot use STL iterators here, since debug iterators use locks. 259 size_t i; 260 for (i = 0; i < saved_mapping.size(); i++) { 261 if (fd == saved_mapping[i].dest) 262 break; 263 } 264 if (i < saved_mapping.size()) 265 continue; 266 if (fd == dir_fd) 267 continue; 268 269 // When running under Valgrind, Valgrind opens several FDs for its 270 // own use and will complain if we try to close them. All of 271 // these FDs are >= |max_fds|, so we can check against that here 272 // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758 273 if (fd < static_cast<int>(max_fds)) { 274 int ret = IGNORE_EINTR(close(fd)); 275 DPCHECK(ret == 0); 276 } 277 } 278} 279 280bool LaunchProcess(const std::vector<std::string>& argv, 281 const LaunchOptions& options, 282 ProcessHandle* process_handle) { 283 size_t fd_shuffle_size = 0; 284 if (options.fds_to_remap) { 285 fd_shuffle_size = options.fds_to_remap->size(); 286 } 287 288 InjectiveMultimap fd_shuffle1; 289 InjectiveMultimap fd_shuffle2; 290 fd_shuffle1.reserve(fd_shuffle_size); 291 fd_shuffle2.reserve(fd_shuffle_size); 292 293 scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]); 294 scoped_ptr<char*[]> new_environ; 295 char* const empty_environ = NULL; 296 char* const* old_environ = GetEnvironment(); 297 if (options.clear_environ) 298 old_environ = &empty_environ; 299 if (!options.environ.empty()) 300 new_environ = AlterEnvironment(old_environ, options.environ); 301 302 sigset_t full_sigset; 303 sigfillset(&full_sigset); 304 const sigset_t orig_sigmask = SetSignalMask(full_sigset); 305 306 pid_t pid; 307#if defined(OS_LINUX) 308 if (options.clone_flags) { 309 // Signal handling in this function assumes the creation of a new 310 // process, so we check that a thread is not being created by mistake 311 // and that signal handling follows the process-creation rules. 312 RAW_CHECK( 313 !(options.clone_flags & (CLONE_SIGHAND | CLONE_THREAD | CLONE_VM))); 314 pid = syscall(__NR_clone, options.clone_flags, 0, 0, 0); 315 } else 316#endif 317 { 318 pid = fork(); 319 } 320 321 // Always restore the original signal mask in the parent. 322 if (pid != 0) { 323 SetSignalMask(orig_sigmask); 324 } 325 326 if (pid < 0) { 327 DPLOG(ERROR) << "fork"; 328 return false; 329 } else if (pid == 0) { 330 // Child process 331 332 // DANGER: no calls to malloc or locks are allowed from now on: 333 // http://crbug.com/36678 334 335 // DANGER: fork() rule: in the child, if you don't end up doing exec*(), 336 // you call _exit() instead of exit(). This is because _exit() does not 337 // call any previously-registered (in the parent) exit handlers, which 338 // might do things like block waiting for threads that don't even exist 339 // in the child. 340 341 // If a child process uses the readline library, the process block forever. 342 // In BSD like OSes including OS X it is safe to assign /dev/null as stdin. 343 // See http://crbug.com/56596. 344 base::ScopedFD null_fd(HANDLE_EINTR(open("/dev/null", O_RDONLY))); 345 if (!null_fd.is_valid()) { 346 RAW_LOG(ERROR, "Failed to open /dev/null"); 347 _exit(127); 348 } 349 350 int new_fd = HANDLE_EINTR(dup2(null_fd.get(), STDIN_FILENO)); 351 if (new_fd != STDIN_FILENO) { 352 RAW_LOG(ERROR, "Failed to dup /dev/null for stdin"); 353 _exit(127); 354 } 355 356 if (options.new_process_group) { 357 // Instead of inheriting the process group ID of the parent, the child 358 // starts off a new process group with pgid equal to its process ID. 359 if (setpgid(0, 0) < 0) { 360 RAW_LOG(ERROR, "setpgid failed"); 361 _exit(127); 362 } 363 } 364 365 // Stop type-profiler. 366 // The profiler should be stopped between fork and exec since it inserts 367 // locks at new/delete expressions. See http://crbug.com/36678. 368 base::type_profiler::Controller::Stop(); 369 370 if (options.maximize_rlimits) { 371 // Some resource limits need to be maximal in this child. 372 for (size_t i = 0; i < options.maximize_rlimits->size(); ++i) { 373 const int resource = (*options.maximize_rlimits)[i]; 374 struct rlimit limit; 375 if (getrlimit(resource, &limit) < 0) { 376 RAW_LOG(WARNING, "getrlimit failed"); 377 } else if (limit.rlim_cur < limit.rlim_max) { 378 limit.rlim_cur = limit.rlim_max; 379 if (setrlimit(resource, &limit) < 0) { 380 RAW_LOG(WARNING, "setrlimit failed"); 381 } 382 } 383 } 384 } 385 386#if defined(OS_MACOSX) 387 RestoreDefaultExceptionHandler(); 388#endif // defined(OS_MACOSX) 389 390 ResetChildSignalHandlersToDefaults(); 391 SetSignalMask(orig_sigmask); 392 393#if 0 394 // When debugging it can be helpful to check that we really aren't making 395 // any hidden calls to malloc. 396 void *malloc_thunk = 397 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); 398 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); 399 memset(reinterpret_cast<void*>(malloc), 0xff, 8); 400#endif // 0 401 402#if defined(OS_CHROMEOS) 403 if (options.ctrl_terminal_fd >= 0) { 404 // Set process' controlling terminal. 405 if (HANDLE_EINTR(setsid()) != -1) { 406 if (HANDLE_EINTR( 407 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { 408 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); 409 } 410 } else { 411 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); 412 } 413 } 414#endif // defined(OS_CHROMEOS) 415 416 if (options.fds_to_remap) { 417 // Cannot use STL iterators here, since debug iterators use locks. 418 for (size_t i = 0; i < options.fds_to_remap->size(); ++i) { 419 const FileHandleMappingVector::value_type& value = 420 (*options.fds_to_remap)[i]; 421 fd_shuffle1.push_back(InjectionArc(value.first, value.second, false)); 422 fd_shuffle2.push_back(InjectionArc(value.first, value.second, false)); 423 } 424 } 425 426 if (!options.environ.empty() || options.clear_environ) 427 SetEnvironment(new_environ.get()); 428 429 // fd_shuffle1 is mutated by this call because it cannot malloc. 430 if (!ShuffleFileDescriptors(&fd_shuffle1)) 431 _exit(127); 432 433 CloseSuperfluousFds(fd_shuffle2); 434 435 // Set NO_NEW_PRIVS by default. Since NO_NEW_PRIVS only exists in kernel 436 // 3.5+, do not check the return value of prctl here. 437#if defined(OS_LINUX) 438#ifndef PR_SET_NO_NEW_PRIVS 439#define PR_SET_NO_NEW_PRIVS 38 440#endif 441 if (!options.allow_new_privs) { 442 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) && errno != EINVAL) { 443 // Only log if the error is not EINVAL (i.e. not supported). 444 RAW_LOG(FATAL, "prctl(PR_SET_NO_NEW_PRIVS) failed"); 445 } 446 } 447#endif 448 449 for (size_t i = 0; i < argv.size(); i++) 450 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); 451 argv_cstr[argv.size()] = NULL; 452 execvp(argv_cstr[0], argv_cstr.get()); 453 454 RAW_LOG(ERROR, "LaunchProcess: failed to execvp:"); 455 RAW_LOG(ERROR, argv_cstr[0]); 456 _exit(127); 457 } else { 458 // Parent process 459 if (options.wait) { 460 // While this isn't strictly disk IO, waiting for another process to 461 // finish is the sort of thing ThreadRestrictions is trying to prevent. 462 base::ThreadRestrictions::AssertIOAllowed(); 463 pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0)); 464 DPCHECK(ret > 0); 465 } 466 467 if (process_handle) 468 *process_handle = pid; 469 } 470 471 return true; 472} 473 474 475bool LaunchProcess(const CommandLine& cmdline, 476 const LaunchOptions& options, 477 ProcessHandle* process_handle) { 478 return LaunchProcess(cmdline.argv(), options, process_handle); 479} 480 481void RaiseProcessToHighPriority() { 482 // On POSIX, we don't actually do anything here. We could try to nice() or 483 // setpriority() or sched_getscheduler, but these all require extra rights. 484} 485 486// Return value used by GetAppOutputInternal to encapsulate the various exit 487// scenarios from the function. 488enum GetAppOutputInternalResult { 489 EXECUTE_FAILURE, 490 EXECUTE_SUCCESS, 491 GOT_MAX_OUTPUT, 492}; 493 494// Executes the application specified by |argv| and wait for it to exit. Stores 495// the output (stdout) in |output|. If |do_search_path| is set, it searches the 496// path for the application; in that case, |envp| must be null, and it will use 497// the current environment. If |do_search_path| is false, |argv[0]| should fully 498// specify the path of the application, and |envp| will be used as the 499// environment. Redirects stderr to /dev/null. 500// If we successfully start the application and get all requested output, we 501// return GOT_MAX_OUTPUT, or if there is a problem starting or exiting 502// the application we return RUN_FAILURE. Otherwise we return EXECUTE_SUCCESS. 503// The GOT_MAX_OUTPUT return value exists so a caller that asks for limited 504// output can treat this as a success, despite having an exit code of SIG_PIPE 505// due to us closing the output pipe. 506// In the case of EXECUTE_SUCCESS, the application exit code will be returned 507// in |*exit_code|, which should be checked to determine if the application 508// ran successfully. 509static GetAppOutputInternalResult GetAppOutputInternal( 510 const std::vector<std::string>& argv, 511 char* const envp[], 512 std::string* output, 513 size_t max_output, 514 bool do_search_path, 515 int* exit_code) { 516 // Doing a blocking wait for another command to finish counts as IO. 517 base::ThreadRestrictions::AssertIOAllowed(); 518 // exit_code must be supplied so calling function can determine success. 519 DCHECK(exit_code); 520 *exit_code = EXIT_FAILURE; 521 522 int pipe_fd[2]; 523 pid_t pid; 524 InjectiveMultimap fd_shuffle1, fd_shuffle2; 525 scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]); 526 527 fd_shuffle1.reserve(3); 528 fd_shuffle2.reserve(3); 529 530 // Either |do_search_path| should be false or |envp| should be null, but not 531 // both. 532 DCHECK(!do_search_path ^ !envp); 533 534 if (pipe(pipe_fd) < 0) 535 return EXECUTE_FAILURE; 536 537 switch (pid = fork()) { 538 case -1: // error 539 close(pipe_fd[0]); 540 close(pipe_fd[1]); 541 return EXECUTE_FAILURE; 542 case 0: // child 543 { 544 // DANGER: no calls to malloc or locks are allowed from now on: 545 // http://crbug.com/36678 546 547#if defined(OS_MACOSX) 548 RestoreDefaultExceptionHandler(); 549#endif 550 551 // Obscure fork() rule: in the child, if you don't end up doing exec*(), 552 // you call _exit() instead of exit(). This is because _exit() does not 553 // call any previously-registered (in the parent) exit handlers, which 554 // might do things like block waiting for threads that don't even exist 555 // in the child. 556 int dev_null = open("/dev/null", O_WRONLY); 557 if (dev_null < 0) 558 _exit(127); 559 560 // Stop type-profiler. 561 // The profiler should be stopped between fork and exec since it inserts 562 // locks at new/delete expressions. See http://crbug.com/36678. 563 base::type_profiler::Controller::Stop(); 564 565 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); 566 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); 567 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); 568 // Adding another element here? Remeber to increase the argument to 569 // reserve(), above. 570 571 for (size_t i = 0; i < fd_shuffle1.size(); ++i) 572 fd_shuffle2.push_back(fd_shuffle1[i]); 573 574 if (!ShuffleFileDescriptors(&fd_shuffle1)) 575 _exit(127); 576 577 CloseSuperfluousFds(fd_shuffle2); 578 579 for (size_t i = 0; i < argv.size(); i++) 580 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); 581 argv_cstr[argv.size()] = NULL; 582 if (do_search_path) 583 execvp(argv_cstr[0], argv_cstr.get()); 584 else 585 execve(argv_cstr[0], argv_cstr.get(), envp); 586 _exit(127); 587 } 588 default: // parent 589 { 590 // Close our writing end of pipe now. Otherwise later read would not 591 // be able to detect end of child's output (in theory we could still 592 // write to the pipe). 593 close(pipe_fd[1]); 594 595 output->clear(); 596 char buffer[256]; 597 size_t output_buf_left = max_output; 598 ssize_t bytes_read = 1; // A lie to properly handle |max_output == 0| 599 // case in the logic below. 600 601 while (output_buf_left > 0) { 602 bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer, 603 std::min(output_buf_left, sizeof(buffer)))); 604 if (bytes_read <= 0) 605 break; 606 output->append(buffer, bytes_read); 607 output_buf_left -= static_cast<size_t>(bytes_read); 608 } 609 close(pipe_fd[0]); 610 611 // Always wait for exit code (even if we know we'll declare 612 // GOT_MAX_OUTPUT). 613 bool success = WaitForExitCode(pid, exit_code); 614 615 // If we stopped because we read as much as we wanted, we return 616 // GOT_MAX_OUTPUT (because the child may exit due to |SIGPIPE|). 617 if (!output_buf_left && bytes_read > 0) 618 return GOT_MAX_OUTPUT; 619 else if (success) 620 return EXECUTE_SUCCESS; 621 return EXECUTE_FAILURE; 622 } 623 } 624} 625 626bool GetAppOutput(const CommandLine& cl, std::string* output) { 627 return GetAppOutput(cl.argv(), output); 628} 629 630bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) { 631 // Run |execve()| with the current environment and store "unlimited" data. 632 int exit_code; 633 GetAppOutputInternalResult result = GetAppOutputInternal( 634 argv, NULL, output, std::numeric_limits<std::size_t>::max(), true, 635 &exit_code); 636 return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS; 637} 638 639// TODO(viettrungluu): Conceivably, we should have a timeout as well, so we 640// don't hang if what we're calling hangs. 641bool GetAppOutputRestricted(const CommandLine& cl, 642 std::string* output, size_t max_output) { 643 // Run |execve()| with the empty environment. 644 char* const empty_environ = NULL; 645 int exit_code; 646 GetAppOutputInternalResult result = GetAppOutputInternal( 647 cl.argv(), &empty_environ, output, max_output, false, &exit_code); 648 return result == GOT_MAX_OUTPUT || (result == EXECUTE_SUCCESS && 649 exit_code == EXIT_SUCCESS); 650} 651 652bool GetAppOutputWithExitCode(const CommandLine& cl, 653 std::string* output, 654 int* exit_code) { 655 // Run |execve()| with the current environment and store "unlimited" data. 656 GetAppOutputInternalResult result = GetAppOutputInternal( 657 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, 658 exit_code); 659 return result == EXECUTE_SUCCESS; 660} 661 662} // namespace base 663