| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <dirent.h> | 5 #include <dirent.h> |
| 6 #include <errno.h> | 6 #include <errno.h> |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <signal.h> | 8 #include <signal.h> |
| 9 #include <stdlib.h> | 9 #include <stdlib.h> |
| 10 #include <sys/resource.h> | 10 #include <sys/resource.h> |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 int cpu = static_cast<int>((system_time_delta * 100 + time_delta / 2) / | 534 int cpu = static_cast<int>((system_time_delta * 100 + time_delta / 2) / |
| 535 time_delta); | 535 time_delta); |
| 536 | 536 |
| 537 last_system_time_ = system_time; | 537 last_system_time_ = system_time; |
| 538 last_time_ = time; | 538 last_time_ = time; |
| 539 | 539 |
| 540 return cpu; | 540 return cpu; |
| 541 } | 541 } |
| 542 #endif | 542 #endif |
| 543 | 543 |
| 544 bool GetAppOutput(const CommandLine& cl, std::string* output) { | 544 // Executes the application specified by |cl| and wait for it to exit. Stores |
| 545 // the output (stdout) in |output|. If |do_search_path| is set, it searches the |
| 546 // path for the application; in that case, |envp| must be null, and it will use |
| 547 // the current environment. If |do_search_path| is false, |cl| should fully |
| 548 // specify the path of the application, and |envp| will be used as the |
| 549 // environment. Redirects stderr to /dev/null. Returns true on success |
| 550 // (application launched and exited cleanly, with exit code indicating success). |
| 551 // |output| is modified only when the function finished successfully. |
| 552 static bool GetAppOutputInternal(const CommandLine& cl, char* const envp[], |
| 553 std::string* output, size_t max_output, |
| 554 bool do_search_path) { |
| 545 int pipe_fd[2]; | 555 int pipe_fd[2]; |
| 546 pid_t pid; | 556 pid_t pid; |
| 547 | 557 |
| 558 // Either |do_search_path| should be false or |envp| should be null, but not |
| 559 // both. |
| 560 DCHECK(!do_search_path ^ !envp); |
| 561 |
| 548 if (pipe(pipe_fd) < 0) | 562 if (pipe(pipe_fd) < 0) |
| 549 return false; | 563 return false; |
| 550 | 564 |
| 551 switch (pid = fork()) { | 565 switch (pid = fork()) { |
| 552 case -1: // error | 566 case -1: // error |
| 553 close(pipe_fd[0]); | 567 close(pipe_fd[0]); |
| 554 close(pipe_fd[1]); | 568 close(pipe_fd[1]); |
| 555 return false; | 569 return false; |
| 556 case 0: // child | 570 case 0: // child |
| 557 { | 571 { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 576 if (!ShuffleFileDescriptors(fd_shuffle)) | 590 if (!ShuffleFileDescriptors(fd_shuffle)) |
| 577 _exit(127); | 591 _exit(127); |
| 578 | 592 |
| 579 CloseSuperfluousFds(fd_shuffle); | 593 CloseSuperfluousFds(fd_shuffle); |
| 580 | 594 |
| 581 const std::vector<std::string> argv = cl.argv(); | 595 const std::vector<std::string> argv = cl.argv(); |
| 582 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]); | 596 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]); |
| 583 for (size_t i = 0; i < argv.size(); i++) | 597 for (size_t i = 0; i < argv.size(); i++) |
| 584 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 598 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
| 585 argv_cstr[argv.size()] = NULL; | 599 argv_cstr[argv.size()] = NULL; |
| 586 execvp(argv_cstr[0], argv_cstr.get()); | 600 if (do_search_path) |
| 601 execvp(argv_cstr[0], argv_cstr.get()); |
| 602 else |
| 603 execve(argv_cstr[0], argv_cstr.get(), envp); |
| 587 _exit(127); | 604 _exit(127); |
| 588 } | 605 } |
| 589 default: // parent | 606 default: // parent |
| 590 { | 607 { |
| 591 // Close our writing end of pipe now. Otherwise later read would not | 608 // Close our writing end of pipe now. Otherwise later read would not |
| 592 // be able to detect end of child's output (in theory we could still | 609 // be able to detect end of child's output (in theory we could still |
| 593 // write to the pipe). | 610 // write to the pipe). |
| 594 close(pipe_fd[1]); | 611 close(pipe_fd[1]); |
| 595 | 612 |
| 596 char buffer[256]; | 613 char buffer[256]; |
| 597 std::string buf_output; | 614 std::string buf_output; |
| 615 size_t output_left = max_output; |
| 616 ssize_t bytes_read = 1; // A lie to properly handle |max_output == 0| |
| 617 // case in the logic below. |
| 598 | 618 |
| 599 while (true) { | 619 while (output_left > 0) { |
| 600 ssize_t bytes_read = | 620 bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer, |
| 601 HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer))); | 621 std::min(output_left, sizeof(buffer)))); |
| 602 if (bytes_read <= 0) | 622 if (bytes_read <= 0) |
| 603 break; | 623 break; |
| 604 buf_output.append(buffer, bytes_read); | 624 buf_output.append(buffer, bytes_read); |
| 625 output_left -= static_cast<size_t>(bytes_read); |
| 605 } | 626 } |
| 606 close(pipe_fd[0]); | 627 close(pipe_fd[0]); |
| 607 | 628 |
| 608 int exit_code = EXIT_FAILURE; | 629 // If we stopped because we read as much as we wanted, we always declare |
| 609 bool success = WaitForExitCode(pid, &exit_code); | 630 // success (because the child may exit due to |SIGPIPE|). |
| 610 if (!success || exit_code != EXIT_SUCCESS) | 631 if (output_left || bytes_read <= 0) { |
| 611 return false; | 632 int exit_code = EXIT_FAILURE; |
| 633 bool success = WaitForExitCode(pid, &exit_code); |
| 634 if (!success || exit_code != EXIT_SUCCESS) |
| 635 return false; |
| 636 } |
| 612 | 637 |
| 613 output->swap(buf_output); | 638 output->swap(buf_output); |
| 614 return true; | 639 return true; |
| 615 } | 640 } |
| 616 } | 641 } |
| 617 } | 642 } |
| 618 | 643 |
| 644 bool GetAppOutput(const CommandLine& cl, std::string* output) { |
| 645 // Run |execve()| with the current environment and store "unlimited" data. |
| 646 return GetAppOutputInternal(cl, NULL, output, |
| 647 std::numeric_limits<std::size_t>::max(), true); |
| 648 } |
| 649 |
| 650 // TODO(viettrungluu): Conceivably, we should have a timeout as well, so we |
| 651 // don't hang if what we're calling hangs. |
| 652 bool GetAppOutputRestricted(const CommandLine& cl, |
| 653 std::string* output, size_t max_output) { |
| 654 // Run |execve()| with the empty environment. |
| 655 char* const empty_environ = NULL; |
| 656 return GetAppOutputInternal(cl, &empty_environ, output, max_output, false); |
| 657 } |
| 658 |
| 619 int GetProcessCount(const std::wstring& executable_name, | 659 int GetProcessCount(const std::wstring& executable_name, |
| 620 const ProcessFilter* filter) { | 660 const ProcessFilter* filter) { |
| 621 int count = 0; | 661 int count = 0; |
| 622 | 662 |
| 623 NamedProcessIterator iter(executable_name, filter); | 663 NamedProcessIterator iter(executable_name, filter); |
| 624 while (iter.NextProcessEntry()) | 664 while (iter.NextProcessEntry()) |
| 625 ++count; | 665 ++count; |
| 626 return count; | 666 return count; |
| 627 } | 667 } |
| 628 | 668 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 const ProcessFilter* filter) { | 706 const ProcessFilter* filter) { |
| 667 bool exited_cleanly = | 707 bool exited_cleanly = |
| 668 WaitForProcessesToExit(executable_name, wait_milliseconds, | 708 WaitForProcessesToExit(executable_name, wait_milliseconds, |
| 669 filter); | 709 filter); |
| 670 if (!exited_cleanly) | 710 if (!exited_cleanly) |
| 671 KillProcesses(executable_name, exit_code, filter); | 711 KillProcesses(executable_name, exit_code, filter); |
| 672 return exited_cleanly; | 712 return exited_cleanly; |
| 673 } | 713 } |
| 674 | 714 |
| 675 } // namespace base | 715 } // namespace base |
| OLD | NEW |