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