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