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