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