Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: base/process_util_posix.cc

Issue 333008: Mac: Implement about:memory. (Closed)
Patch Set: Merged ToT. Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/process_util.h ('k') | base/process_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « base/process_util.h ('k') | base/process_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698