process_util_posix.cc revision c7f5f8508d98d5952d42ed7648c2a8f30a4da156
1// Copyright (c) 2006-2008 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/compiler_specific.h" 20#include "base/debug_util.h" 21#include "base/eintr_wrapper.h" 22#include "base/logging.h" 23#include "base/platform_thread.h" 24#include "base/process_util.h" 25#include "base/rand_util.h" 26#include "base/scoped_ptr.h" 27#include "base/sys_info.h" 28#include "base/time.h" 29#include "base/waitable_event.h" 30 31#if defined(OS_MACOSX) 32#include "base/mach_ipc_mac.h" 33#endif 34 35const int kMicrosecondsPerSecond = 1000000; 36 37namespace base { 38 39namespace { 40 41int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds, 42 bool* success) { 43 // This POSIX version of this function only guarantees that we wait no less 44 // than |wait_milliseconds| for the proces to exit. The child process may 45 // exit sometime before the timeout has ended but we may still block for 46 // up to 0.25 seconds after the fact. 47 // 48 // waitpid() has no direct support on POSIX for specifying a timeout, you can 49 // either ask it to block indefinitely or return immediately (WNOHANG). 50 // When a child process terminates a SIGCHLD signal is sent to the parent. 51 // Catching this signal would involve installing a signal handler which may 52 // affect other parts of the application and would be difficult to debug. 53 // 54 // Our strategy is to call waitpid() once up front to check if the process 55 // has already exited, otherwise to loop for wait_milliseconds, sleeping for 56 // at most 0.25 secs each time using usleep() and then calling waitpid(). 57 // 58 // usleep() is speced to exit if a signal is received for which a handler 59 // has been installed. This means that when a SIGCHLD is sent, it will exit 60 // depending on behavior external to this function. 61 // 62 // This function is used primarily for unit tests, if we want to use it in 63 // the application itself it would probably be best to examine other routes. 64 int status = -1; 65 pid_t ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG)); 66 static const int64 kQuarterSecondInMicroseconds = kMicrosecondsPerSecond / 4; 67 68 // If the process hasn't exited yet, then sleep and try again. 69 Time wakeup_time = Time::Now() + TimeDelta::FromMilliseconds( 70 wait_milliseconds); 71 while (ret_pid == 0) { 72 Time now = Time::Now(); 73 if (now > wakeup_time) 74 break; 75 // Guaranteed to be non-negative! 76 int64 sleep_time_usecs = (wakeup_time - now).InMicroseconds(); 77 // Don't sleep for more than 0.25 secs at a time. 78 if (sleep_time_usecs > kQuarterSecondInMicroseconds) { 79 sleep_time_usecs = kQuarterSecondInMicroseconds; 80 } 81 82 // usleep() will return 0 and set errno to EINTR on receipt of a signal 83 // such as SIGCHLD. 84 usleep(sleep_time_usecs); 85 ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG)); 86 } 87 88 if (success) 89 *success = (ret_pid != -1); 90 91 return status; 92} 93 94void StackDumpSignalHandler(int signal) { 95 StackTrace().PrintBacktrace(); 96 _exit(1); 97} 98 99} // namespace 100 101ProcessId GetCurrentProcId() { 102 return getpid(); 103} 104 105ProcessHandle GetCurrentProcessHandle() { 106 return GetCurrentProcId(); 107} 108 109bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) { 110 // On Posix platforms, process handles are the same as PIDs, so we 111 // don't need to do anything. 112 *handle = pid; 113 return true; 114} 115 116bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) { 117 // On POSIX permissions are checked for each operation on process, 118 // not when opening a "handle". 119 return OpenProcessHandle(pid, handle); 120} 121 122void CloseProcessHandle(ProcessHandle process) { 123 // See OpenProcessHandle, nothing to do. 124 return; 125} 126 127ProcessId GetProcId(ProcessHandle process) { 128 return process; 129} 130 131// Attempts to kill the process identified by the given process 132// entry structure. Ignores specified exit_code; posix can't force that. 133// Returns true if this is successful, false otherwise. 134bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) { 135 DCHECK_GT(process_id, 1) << " tried to kill invalid process_id"; 136 if (process_id <= 1) 137 return false; 138 139 bool result = kill(process_id, SIGTERM) == 0; 140 141 if (result && wait) { 142 int tries = 60; 143 // The process may not end immediately due to pending I/O 144 bool exited = false; 145 while (tries-- > 0) { 146 pid_t pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG)); 147 if (pid == process_id) { 148 exited = true; 149 break; 150 } 151 152 sleep(1); 153 } 154 155 if (!exited) 156 result = kill(process_id, SIGKILL) == 0; 157 } 158 159 if (!result) 160 DPLOG(ERROR) << "Unable to terminate process " << process_id; 161 162 return result; 163} 164 165// A class to handle auto-closing of DIR*'s. 166class ScopedDIRClose { 167 public: 168 inline void operator()(DIR* x) const { 169 if (x) { 170 closedir(x); 171 } 172 } 173}; 174typedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR; 175 176void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) { 177#if defined(OS_LINUX) 178 static const rlim_t kSystemDefaultMaxFds = 8192; 179 static const char fd_dir[] = "/proc/self/fd"; 180#elif defined(OS_MACOSX) 181 static const rlim_t kSystemDefaultMaxFds = 256; 182 static const char fd_dir[] = "/dev/fd"; 183#elif defined(OS_FREEBSD) 184 static const rlim_t kSystemDefaultMaxFds = 8192; 185 static const char fd_dir[] = "/dev/fd"; 186#elif defined(OS_OPENBSD) 187 static const rlim_t kSystemDefaultMaxFds = 256; 188 static const char fd_dir[] = "/dev/fd"; 189#endif 190 std::set<int> saved_fds; 191 192 // Get the maximum number of FDs possible. 193 struct rlimit nofile; 194 rlim_t max_fds; 195 if (getrlimit(RLIMIT_NOFILE, &nofile)) { 196 // getrlimit failed. Take a best guess. 197 max_fds = kSystemDefaultMaxFds; 198 DLOG(ERROR) << "getrlimit(RLIMIT_NOFILE) failed: " << errno; 199 } else { 200 max_fds = nofile.rlim_cur; 201 } 202 203 if (max_fds > INT_MAX) 204 max_fds = INT_MAX; 205 206 // Don't close stdin, stdout and stderr 207 saved_fds.insert(STDIN_FILENO); 208 saved_fds.insert(STDOUT_FILENO); 209 saved_fds.insert(STDERR_FILENO); 210 211 for (base::InjectiveMultimap::const_iterator 212 i = saved_mapping.begin(); i != saved_mapping.end(); ++i) { 213 saved_fds.insert(i->dest); 214 } 215 216 ScopedDIR dir_closer(opendir(fd_dir)); 217 DIR *dir = dir_closer.get(); 218 if (NULL == dir) { 219 DLOG(ERROR) << "Unable to open " << fd_dir; 220 221 // Fallback case: Try every possible fd. 222 for (rlim_t i = 0; i < max_fds; ++i) { 223 const int fd = static_cast<int>(i); 224 if (saved_fds.find(fd) != saved_fds.end()) 225 continue; 226 227 // Since we're just trying to close anything we can find, 228 // ignore any error return values of close(). 229 int unused ALLOW_UNUSED = HANDLE_EINTR(close(fd)); 230 } 231 return; 232 } 233 int dir_fd = dirfd(dir); 234 235 struct dirent *ent; 236 while ((ent = readdir(dir))) { 237 // Skip . and .. entries. 238 if (ent->d_name[0] == '.') 239 continue; 240 241 char *endptr; 242 errno = 0; 243 const long int fd = strtol(ent->d_name, &endptr, 10); 244 if (ent->d_name[0] == 0 || *endptr || fd < 0 || errno) 245 continue; 246 if (saved_fds.find(fd) != saved_fds.end()) 247 continue; 248 if (fd == dir_fd) 249 continue; 250 251 // When running under Valgrind, Valgrind opens several FDs for its 252 // own use and will complain if we try to close them. All of 253 // these FDs are >= |max_fds|, so we can check against that here 254 // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758 255 if (fd < static_cast<int>(max_fds)) { 256 int ret = HANDLE_EINTR(close(fd)); 257 DPCHECK(ret == 0); 258 } 259 } 260} 261 262// Sets all file descriptors to close on exec except for stdin, stdout 263// and stderr. 264// TODO(agl): Remove this function. It's fundamentally broken for multithreaded 265// apps. 266void SetAllFDsToCloseOnExec() { 267#if defined(OS_LINUX) 268 const char fd_dir[] = "/proc/self/fd"; 269#elif defined(OS_MACOSX) || defined(OS_FREEBSD) 270 const char fd_dir[] = "/dev/fd"; 271#endif 272 ScopedDIR dir_closer(opendir(fd_dir)); 273 DIR *dir = dir_closer.get(); 274 if (NULL == dir) { 275 DLOG(ERROR) << "Unable to open " << fd_dir; 276 return; 277 } 278 279 struct dirent *ent; 280 while ((ent = readdir(dir))) { 281 // Skip . and .. entries. 282 if (ent->d_name[0] == '.') 283 continue; 284 int i = atoi(ent->d_name); 285 // We don't close stdin, stdout or stderr. 286 if (i <= STDERR_FILENO) 287 continue; 288 289 int flags = fcntl(i, F_GETFD); 290 if ((flags == -1) || (fcntl(i, F_SETFD, flags | FD_CLOEXEC) == -1)) { 291 DLOG(ERROR) << "fcntl failure."; 292 } 293 } 294} 295 296#if defined(OS_MACOSX) 297static std::string MachErrorCode(kern_return_t err) { 298 return StringPrintf("0x%x %s", err, mach_error_string(err)); 299} 300 301// Forks the current process and returns the child's |task_t| in the parent 302// process. 303static pid_t fork_and_get_task(task_t* child_task) { 304 const int kTimeoutMs = 100; 305 kern_return_t err; 306 307 // Put a random number into the channel name, so that a compromised renderer 308 // can't pretend being the child that's forked off. 309 std::string mach_connection_name = StringPrintf( 310 "com.google.Chrome.samplingfork.%p.%d", 311 child_task, base::RandInt(0, std::numeric_limits<int>::max())); 312 ReceivePort parent_recv_port(mach_connection_name.c_str()); 313 314 // Error handling philosophy: If Mach IPC fails, don't touch |child_task| but 315 // return a valid pid. If IPC fails in the child, the parent will have to wait 316 // until kTimeoutMs is over. This is not optimal, but I've never seen it 317 // happen, and stuff should still mostly work. 318 pid_t pid = fork(); 319 switch (pid) { 320 case -1: 321 return pid; 322 case 0: { // child 323 MachSendMessage child_message(/* id= */0); 324 if (!child_message.AddDescriptor(mach_task_self())) { 325 LOG(ERROR) << "child AddDescriptor(mach_task_self()) failed."; 326 return pid; 327 } 328 329 MachPortSender child_sender(mach_connection_name.c_str()); 330 err = child_sender.SendMessage(child_message, kTimeoutMs); 331 if (err != KERN_SUCCESS) { 332 LOG(ERROR) << "child SendMessage() failed: " << MachErrorCode(err); 333 return pid; 334 } 335 break; 336 } 337 default: { // parent 338 MachReceiveMessage child_message; 339 err = parent_recv_port.WaitForMessage(&child_message, kTimeoutMs); 340 if (err != KERN_SUCCESS) { 341 LOG(ERROR) << "parent WaitForMessage() failed: " << MachErrorCode(err); 342 return pid; 343 } 344 345 if (child_message.GetTranslatedPort(0) == MACH_PORT_NULL) { 346 LOG(ERROR) << "parent GetTranslatedPort(0) failed."; 347 return pid; 348 } 349 *child_task = child_message.GetTranslatedPort(0); 350 break; 351 } 352 } 353 return pid; 354} 355 356bool LaunchApp(const std::vector<std::string>& argv, 357 const environment_vector& environ, 358 const file_handle_mapping_vector& fds_to_remap, 359 bool wait, ProcessHandle* process_handle) { 360 return LaunchAppAndGetTask( 361 argv, environ, fds_to_remap, wait, NULL, process_handle); 362} 363#endif // defined(OS_MACOSX) 364 365#if defined(OS_MACOSX) 366bool LaunchAppAndGetTask( 367#else 368bool LaunchApp( 369#endif 370 const std::vector<std::string>& argv, 371 const environment_vector& environ, 372 const file_handle_mapping_vector& fds_to_remap, 373 bool wait, 374#if defined(OS_MACOSX) 375 task_t* task_handle, 376#endif 377 ProcessHandle* process_handle) { 378 pid_t pid; 379#if defined(OS_MACOSX) 380 if (task_handle == NULL) { 381 pid = fork(); 382 } else { 383 // On OS X, the task_t for a process is needed for several reasons. Sadly, 384 // the function task_for_pid() requires privileges a normal user doesn't 385 // have. Instead, a short-lived Mach IPC connection is opened between parent 386 // and child, and the child sends its task_t to the parent at fork time. 387 *task_handle = MACH_PORT_NULL; 388 pid = fork_and_get_task(task_handle); 389 } 390#else 391 pid = fork(); 392#endif 393 if (pid < 0) 394 return false; 395 396 if (pid == 0) { 397 // Child process 398#if defined(OS_MACOSX) 399 RestoreDefaultExceptionHandler(); 400#endif 401 402 InjectiveMultimap fd_shuffle; 403 for (file_handle_mapping_vector::const_iterator 404 it = fds_to_remap.begin(); it != fds_to_remap.end(); ++it) { 405 fd_shuffle.push_back(InjectionArc(it->first, it->second, false)); 406 } 407 408 for (environment_vector::const_iterator it = environ.begin(); 409 it != environ.end(); ++it) { 410 if (it->first.empty()) 411 continue; 412 413 if (it->second.empty()) { 414 unsetenv(it->first.c_str()); 415 } else { 416 setenv(it->first.c_str(), it->second.c_str(), 1); 417 } 418 } 419 420 // Obscure fork() rule: in the child, if you don't end up doing exec*(), 421 // you call _exit() instead of exit(). This is because _exit() does not 422 // call any previously-registered (in the parent) exit handlers, which 423 // might do things like block waiting for threads that don't even exist 424 // in the child. 425 if (!ShuffleFileDescriptors(fd_shuffle)) 426 _exit(127); 427 428 // If we are using the SUID sandbox, it sets a magic environment variable 429 // ("SBX_D"), so we remove that variable from the environment here on the 430 // off chance that it's already set. 431 unsetenv("SBX_D"); 432 433 CloseSuperfluousFds(fd_shuffle); 434 435 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]); 436 for (size_t i = 0; i < argv.size(); i++) 437 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); 438 argv_cstr[argv.size()] = NULL; 439 execvp(argv_cstr[0], argv_cstr.get()); 440 PLOG(ERROR) << "LaunchApp: execvp(" << argv_cstr[0] << ") failed"; 441 _exit(127); 442 } else { 443 // Parent process 444 if (wait) { 445 pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0)); 446 DPCHECK(ret > 0); 447 } 448 449 if (process_handle) 450 *process_handle = pid; 451 } 452 453 return true; 454} 455 456bool LaunchApp(const std::vector<std::string>& argv, 457 const file_handle_mapping_vector& fds_to_remap, 458 bool wait, ProcessHandle* process_handle) { 459 base::environment_vector no_env; 460 return LaunchApp(argv, no_env, fds_to_remap, wait, process_handle); 461} 462 463bool LaunchApp(const CommandLine& cl, 464 bool wait, bool start_hidden, 465 ProcessHandle* process_handle) { 466 file_handle_mapping_vector no_files; 467 return LaunchApp(cl.argv(), no_files, wait, process_handle); 468} 469 470#if !defined(OS_MACOSX) 471ProcessMetrics::ProcessMetrics(ProcessHandle process) 472#else 473ProcessMetrics::ProcessMetrics(ProcessHandle process, 474 ProcessMetrics::PortProvider* port_provider) 475#endif 476 : process_(process), 477 last_time_(0), 478 last_system_time_(0) 479#if defined(OS_LINUX) 480 , last_cpu_(0) 481#elif defined(OS_MACOSX) 482 , port_provider_(port_provider) 483#endif 484{ 485 processor_count_ = base::SysInfo::NumberOfProcessors(); 486} 487 488// static 489#if !defined(OS_MACOSX) 490ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) { 491 return new ProcessMetrics(process); 492} 493#else 494ProcessMetrics* ProcessMetrics::CreateProcessMetrics( 495 ProcessHandle process, 496 ProcessMetrics::PortProvider* port_provider) { 497 return new ProcessMetrics(process, port_provider); 498} 499#endif 500 501ProcessMetrics::~ProcessMetrics() { } 502 503void EnableTerminationOnHeapCorruption() { 504 // On POSIX, there nothing to do AFAIK. 505} 506 507bool EnableInProcessStackDumping() { 508 // When running in an application, our code typically expects SIGPIPE 509 // to be ignored. Therefore, when testing that same code, it should run 510 // with SIGPIPE ignored as well. 511 struct sigaction action; 512 action.sa_handler = SIG_IGN; 513 action.sa_flags = 0; 514 sigemptyset(&action.sa_mask); 515 bool success = (sigaction(SIGPIPE, &action, NULL) == 0); 516 517 // TODO(phajdan.jr): Catch other crashy signals, like SIGABRT. 518 success &= (signal(SIGSEGV, &StackDumpSignalHandler) != SIG_ERR); 519 success &= (signal(SIGILL, &StackDumpSignalHandler) != SIG_ERR); 520 success &= (signal(SIGBUS, &StackDumpSignalHandler) != SIG_ERR); 521 success &= (signal(SIGFPE, &StackDumpSignalHandler) != SIG_ERR); 522 return success; 523} 524 525void AttachToConsole() { 526 // On POSIX, there nothing to do AFAIK. Maybe create a new console if none 527 // exist? 528} 529 530void RaiseProcessToHighPriority() { 531 // On POSIX, we don't actually do anything here. We could try to nice() or 532 // setpriority() or sched_getscheduler, but these all require extra rights. 533} 534 535bool DidProcessCrash(bool* child_exited, ProcessHandle handle) { 536 int status; 537 const pid_t result = HANDLE_EINTR(waitpid(handle, &status, WNOHANG)); 538 if (result == -1) { 539 PLOG(ERROR) << "waitpid(" << handle << ")"; 540 if (child_exited) 541 *child_exited = false; 542 return false; 543 } else if (result == 0) { 544 // the child hasn't exited yet. 545 if (child_exited) 546 *child_exited = false; 547 return false; 548 } 549 550 if (child_exited) 551 *child_exited = true; 552 553 if (WIFSIGNALED(status)) { 554 switch (WTERMSIG(status)) { 555 case SIGSEGV: 556 case SIGILL: 557 case SIGABRT: 558 case SIGFPE: 559 return true; 560 default: 561 return false; 562 } 563 } 564 565 if (WIFEXITED(status)) 566 return WEXITSTATUS(status) != 0; 567 568 return false; 569} 570 571bool WaitForExitCode(ProcessHandle handle, int* exit_code) { 572 int status; 573 if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) { 574 NOTREACHED(); 575 return false; 576 } 577 578 if (WIFEXITED(status)) { 579 *exit_code = WEXITSTATUS(status); 580 return true; 581 } 582 583 // If it didn't exit cleanly, it must have been signaled. 584 DCHECK(WIFSIGNALED(status)); 585 return false; 586} 587 588bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) { 589 bool waitpid_success; 590 int status; 591 if (wait_milliseconds == base::kNoTimeout) 592 waitpid_success = (HANDLE_EINTR(waitpid(handle, &status, 0)) != -1); 593 else 594 status = WaitpidWithTimeout(handle, wait_milliseconds, &waitpid_success); 595 if (status != -1) { 596 DCHECK(waitpid_success); 597 return WIFEXITED(status); 598 } else { 599 return false; 600 } 601} 602 603bool CrashAwareSleep(ProcessHandle handle, int64 wait_milliseconds) { 604 bool waitpid_success; 605 int status = WaitpidWithTimeout(handle, wait_milliseconds, &waitpid_success); 606 if (status != -1) { 607 DCHECK(waitpid_success); 608 return !(WIFEXITED(status) || WIFSIGNALED(status)); 609 } else { 610 // If waitpid returned with an error, then the process doesn't exist 611 // (which most probably means it didn't exist before our call). 612 return waitpid_success; 613 } 614} 615 616int64 TimeValToMicroseconds(const struct timeval& tv) { 617 return tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec; 618} 619 620// Executes the application specified by |cl| and wait for it to exit. Stores 621// the output (stdout) in |output|. If |do_search_path| is set, it searches the 622// path for the application; in that case, |envp| must be null, and it will use 623// the current environment. If |do_search_path| is false, |cl| should fully 624// specify the path of the application, and |envp| will be used as the 625// environment. Redirects stderr to /dev/null. Returns true on success 626// (application launched and exited cleanly, with exit code indicating success). 627// |output| is modified only when the function finished successfully. 628static bool GetAppOutputInternal(const CommandLine& cl, char* const envp[], 629 std::string* output, size_t max_output, 630 bool do_search_path) { 631 int pipe_fd[2]; 632 pid_t pid; 633 634 // Either |do_search_path| should be false or |envp| should be null, but not 635 // both. 636 DCHECK(!do_search_path ^ !envp); 637 638 if (pipe(pipe_fd) < 0) 639 return false; 640 641 switch (pid = fork()) { 642 case -1: // error 643 close(pipe_fd[0]); 644 close(pipe_fd[1]); 645 return false; 646 case 0: // child 647 { 648#if defined(OS_MACOSX) 649 RestoreDefaultExceptionHandler(); 650#endif 651 652 // Obscure fork() rule: in the child, if you don't end up doing exec*(), 653 // you call _exit() instead of exit(). This is because _exit() does not 654 // call any previously-registered (in the parent) exit handlers, which 655 // might do things like block waiting for threads that don't even exist 656 // in the child. 657 int dev_null = open("/dev/null", O_WRONLY); 658 if (dev_null < 0) 659 _exit(127); 660 661 InjectiveMultimap fd_shuffle; 662 fd_shuffle.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); 663 fd_shuffle.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); 664 fd_shuffle.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); 665 666 if (!ShuffleFileDescriptors(fd_shuffle)) 667 _exit(127); 668 669 CloseSuperfluousFds(fd_shuffle); 670 671 const std::vector<std::string> argv = cl.argv(); 672 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]); 673 for (size_t i = 0; i < argv.size(); i++) 674 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); 675 argv_cstr[argv.size()] = NULL; 676 if (do_search_path) 677 execvp(argv_cstr[0], argv_cstr.get()); 678 else 679 execve(argv_cstr[0], argv_cstr.get(), envp); 680 _exit(127); 681 } 682 default: // parent 683 { 684 // Close our writing end of pipe now. Otherwise later read would not 685 // be able to detect end of child's output (in theory we could still 686 // write to the pipe). 687 close(pipe_fd[1]); 688 689 char buffer[256]; 690 std::string output_buf; 691 size_t output_buf_left = max_output; 692 ssize_t bytes_read = 1; // A lie to properly handle |max_output == 0| 693 // case in the logic below. 694 695 while (output_buf_left > 0) { 696 bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer, 697 std::min(output_buf_left, sizeof(buffer)))); 698 if (bytes_read <= 0) 699 break; 700 output_buf.append(buffer, bytes_read); 701 output_buf_left -= static_cast<size_t>(bytes_read); 702 } 703 close(pipe_fd[0]); 704 705 // Always wait for exit code (even if we know we'll declare success). 706 int exit_code = EXIT_FAILURE; 707 bool success = WaitForExitCode(pid, &exit_code); 708 709 // If we stopped because we read as much as we wanted, we always declare 710 // success (because the child may exit due to |SIGPIPE|). 711 if (output_buf_left || bytes_read <= 0) { 712 if (!success || exit_code != EXIT_SUCCESS) 713 return false; 714 } 715 716 output->swap(output_buf); 717 return true; 718 } 719 } 720} 721 722bool GetAppOutput(const CommandLine& cl, std::string* output) { 723 // Run |execve()| with the current environment and store "unlimited" data. 724 return GetAppOutputInternal(cl, NULL, output, 725 std::numeric_limits<std::size_t>::max(), true); 726} 727 728// TODO(viettrungluu): Conceivably, we should have a timeout as well, so we 729// don't hang if what we're calling hangs. 730bool GetAppOutputRestricted(const CommandLine& cl, 731 std::string* output, size_t max_output) { 732 // Run |execve()| with the empty environment. 733 char* const empty_environ = NULL; 734 return GetAppOutputInternal(cl, &empty_environ, output, max_output, false); 735} 736 737int GetProcessCount(const std::wstring& executable_name, 738 const ProcessFilter* filter) { 739 int count = 0; 740 741 NamedProcessIterator iter(executable_name, filter); 742 while (iter.NextProcessEntry()) 743 ++count; 744 return count; 745} 746 747bool KillProcesses(const std::wstring& executable_name, int exit_code, 748 const ProcessFilter* filter) { 749 bool result = true; 750 const ProcessEntry* entry; 751 752 NamedProcessIterator iter(executable_name, filter); 753 while ((entry = iter.NextProcessEntry()) != NULL) 754 result = KillProcess((*entry).pid, exit_code, true) && result; 755 756 return result; 757} 758 759bool WaitForProcessesToExit(const std::wstring& executable_name, 760 int64 wait_milliseconds, 761 const ProcessFilter* filter) { 762 bool result = false; 763 764 // TODO(port): This is inefficient, but works if there are multiple procs. 765 // TODO(port): use waitpid to avoid leaving zombies around 766 767 base::Time end_time = base::Time::Now() + 768 base::TimeDelta::FromMilliseconds(wait_milliseconds); 769 do { 770 NamedProcessIterator iter(executable_name, filter); 771 if (!iter.NextProcessEntry()) { 772 result = true; 773 break; 774 } 775 PlatformThread::Sleep(100); 776 } while ((base::Time::Now() - end_time) > base::TimeDelta()); 777 778 return result; 779} 780 781bool CleanupProcesses(const std::wstring& executable_name, 782 int64 wait_milliseconds, 783 int exit_code, 784 const ProcessFilter* filter) { 785 bool exited_cleanly = 786 WaitForProcessesToExit(executable_name, wait_milliseconds, 787 filter); 788 if (!exited_cleanly) 789 KillProcesses(executable_name, exit_code, filter); 790 return exited_cleanly; 791} 792 793} // namespace base 794