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 35 const int kMicrosecondsPerSecond = 1000000; 36 37 namespace base { 38 39 namespace { 40 41 int 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 94 void StackDumpSignalHandler(int signal) { 95 StackTrace().PrintBacktrace(); 96 _exit(1); 97 } 98 99 } // namespace 100 101 ProcessId GetCurrentProcId() { 102 return getpid(); 103 } 104 105 ProcessHandle GetCurrentProcessHandle() { 106 return GetCurrentProcId(); 107 } 108 109 bool 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 116 bool 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 122 void CloseProcessHandle(ProcessHandle process) { 123 // See OpenProcessHandle, nothing to do. 124 return; 125 } 126 127 ProcessId 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. 134 bool 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. 166 class ScopedDIRClose { 167 public: 168 inline void operator()(DIR* x) const { 169 if (x) { 170 closedir(x); 171 } 172 } 173 }; 174 typedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR; 175 176 void 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. 266 void 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) 297 static 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. 303 static 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 356 bool 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) 366 bool LaunchAppAndGetTask( 367 #else 368 bool 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 456 bool 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 463 bool 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) 471 ProcessMetrics::ProcessMetrics(ProcessHandle process) 472 #else 473 ProcessMetrics::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) 490 ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) { 491 return new ProcessMetrics(process); 492 } 493 #else 494 ProcessMetrics* ProcessMetrics::CreateProcessMetrics( 495 ProcessHandle process, 496 ProcessMetrics::PortProvider* port_provider) { 497 return new ProcessMetrics(process, port_provider); 498 } 499 #endif 500 501 ProcessMetrics::~ProcessMetrics() { } 502 503 void EnableTerminationOnHeapCorruption() { 504 // On POSIX, there nothing to do AFAIK. 505 } 506 507 bool 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 525 void AttachToConsole() { 526 // On POSIX, there nothing to do AFAIK. Maybe create a new console if none 527 // exist? 528 } 529 530 void 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 535 bool 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 571 bool 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 588 bool 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 603 bool 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 616 int64 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. 628 static 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 722 bool 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. 730 bool 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 737 int 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 747 bool 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 759 bool 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 781 bool 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