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