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