OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/process/launch.h" | 5 #include "base/process/launch.h" |
6 | 6 |
7 #include <dirent.h> | 7 #include <dirent.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <sched.h> | 10 #include <sched.h> |
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
504 } | 504 } |
505 | 505 |
506 return Process(pid); | 506 return Process(pid); |
507 } | 507 } |
508 | 508 |
509 void RaiseProcessToHighPriority() { | 509 void RaiseProcessToHighPriority() { |
510 // On POSIX, we don't actually do anything here. We could try to nice() or | 510 // On POSIX, we don't actually do anything here. We could try to nice() or |
511 // setpriority() or sched_getscheduler, but these all require extra rights. | 511 // setpriority() or sched_getscheduler, but these all require extra rights. |
512 } | 512 } |
513 | 513 |
514 // Return value used by GetAppOutputInternal to encapsulate the various exit | |
515 // scenarios from the function. | |
516 enum GetAppOutputInternalResult { | |
517 EXECUTE_FAILURE, | |
518 EXECUTE_SUCCESS, | |
519 GOT_MAX_OUTPUT, | |
520 }; | |
521 | |
522 // Executes the application specified by |argv| and wait for it to exit. Stores | 514 // Executes the application specified by |argv| and wait for it to exit. Stores |
523 // the output (stdout) in |output|. If |do_search_path| is set, it searches the | 515 // the output (stdout) in |output|. If |do_search_path| is set, it searches the |
524 // path for the application; in that case, |envp| must be null, and it will use | 516 // path for the application; in that case, |envp| must be null, and it will use |
525 // the current environment. If |do_search_path| is false, |argv[0]| should fully | 517 // the current environment. If |do_search_path| is false, |argv[0]| should fully |
526 // specify the path of the application, and |envp| will be used as the | 518 // specify the path of the application, and |envp| will be used as the |
527 // environment. If |include_stderr| is true, includes stderr otherwise redirects | 519 // environment. If |include_stderr| is true, includes stderr otherwise redirects |
528 // it to /dev/null. | 520 // it to /dev/null. |
529 // If we successfully start the application and get all requested output, we | 521 // The return value of the function indicates success or failure. In the case of |
530 // return GOT_MAX_OUTPUT, or if there is a problem starting or exiting | 522 // success, the application exit code will be returned in |*exit_code|, which |
531 // the application we return RUN_FAILURE. Otherwise we return EXECUTE_SUCCESS. | 523 // should be checked to determine if the application ran successfully. |
532 // The GOT_MAX_OUTPUT return value exists so a caller that asks for limited | 524 static bool GetAppOutputInternal( |
533 // output can treat this as a success, despite having an exit code of SIG_PIPE | |
534 // due to us closing the output pipe. | |
535 // In the case of EXECUTE_SUCCESS, the application exit code will be returned | |
536 // in |*exit_code|, which should be checked to determine if the application | |
537 // ran successfully. | |
538 static GetAppOutputInternalResult GetAppOutputInternal( | |
539 const std::vector<std::string>& argv, | 525 const std::vector<std::string>& argv, |
540 char* const envp[], | 526 char* const envp[], |
541 bool include_stderr, | 527 bool include_stderr, |
542 std::string* output, | 528 std::string* output, |
543 size_t max_output, | |
544 bool do_search_path, | 529 bool do_search_path, |
545 int* exit_code) { | 530 int* exit_code) { |
546 // Doing a blocking wait for another command to finish counts as IO. | 531 // Doing a blocking wait for another command to finish counts as IO. |
547 base::ThreadRestrictions::AssertIOAllowed(); | 532 base::ThreadRestrictions::AssertIOAllowed(); |
548 // exit_code must be supplied so calling function can determine success. | 533 // exit_code must be supplied so calling function can determine success. |
549 DCHECK(exit_code); | 534 DCHECK(exit_code); |
550 *exit_code = EXIT_FAILURE; | 535 *exit_code = EXIT_FAILURE; |
551 | 536 |
552 int pipe_fd[2]; | 537 int pipe_fd[2]; |
553 pid_t pid; | 538 pid_t pid; |
554 InjectiveMultimap fd_shuffle1, fd_shuffle2; | 539 InjectiveMultimap fd_shuffle1, fd_shuffle2; |
555 std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]); | 540 std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]); |
556 | 541 |
557 fd_shuffle1.reserve(3); | 542 fd_shuffle1.reserve(3); |
558 fd_shuffle2.reserve(3); | 543 fd_shuffle2.reserve(3); |
559 | 544 |
560 // Either |do_search_path| should be false or |envp| should be null, but not | 545 // Either |do_search_path| should be false or |envp| should be null, but not |
561 // both. | 546 // both. |
562 DCHECK(!do_search_path ^ !envp); | 547 DCHECK(!do_search_path ^ !envp); |
563 | 548 |
564 if (pipe(pipe_fd) < 0) | 549 if (pipe(pipe_fd) < 0) |
565 return EXECUTE_FAILURE; | 550 return false; |
566 | 551 |
567 switch (pid = fork()) { | 552 switch (pid = fork()) { |
568 case -1: // error | 553 case -1: // error |
569 close(pipe_fd[0]); | 554 close(pipe_fd[0]); |
570 close(pipe_fd[1]); | 555 close(pipe_fd[1]); |
571 return EXECUTE_FAILURE; | 556 return false; |
572 case 0: // child | 557 case 0: // child |
573 { | 558 { |
574 // DANGER: no calls to malloc or locks are allowed from now on: | 559 // DANGER: no calls to malloc or locks are allowed from now on: |
575 // http://crbug.com/36678 | 560 // http://crbug.com/36678 |
576 | 561 |
577 #if defined(OS_MACOSX) | 562 #if defined(OS_MACOSX) |
578 RestoreDefaultExceptionHandler(); | 563 RestoreDefaultExceptionHandler(); |
579 #endif | 564 #endif |
580 | 565 |
581 // Obscure fork() rule: in the child, if you don't end up doing exec*(), | 566 // Obscure fork() rule: in the child, if you don't end up doing exec*(), |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
614 } | 599 } |
615 default: // parent | 600 default: // parent |
616 { | 601 { |
617 // Close our writing end of pipe now. Otherwise later read would not | 602 // Close our writing end of pipe now. Otherwise later read would not |
618 // be able to detect end of child's output (in theory we could still | 603 // be able to detect end of child's output (in theory we could still |
619 // write to the pipe). | 604 // write to the pipe). |
620 close(pipe_fd[1]); | 605 close(pipe_fd[1]); |
621 | 606 |
622 output->clear(); | 607 output->clear(); |
623 char buffer[256]; | 608 char buffer[256]; |
624 size_t output_buf_left = max_output; | 609 ssize_t bytes_read = 0; |
Lei Zhang
2016/07/04 20:33:04
This can be declared in the while loop now.
benwells
2016/07/05 03:48:38
Done.
| |
625 ssize_t bytes_read = 1; // A lie to properly handle |max_output == 0| | |
626 // case in the logic below. | |
627 | 610 |
628 while (output_buf_left > 0) { | 611 while (true) { |
629 bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer, | 612 bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer))); |
630 std::min(output_buf_left, sizeof(buffer)))); | |
631 if (bytes_read <= 0) | 613 if (bytes_read <= 0) |
632 break; | 614 break; |
633 output->append(buffer, bytes_read); | 615 output->append(buffer, bytes_read); |
634 output_buf_left -= static_cast<size_t>(bytes_read); | |
635 } | 616 } |
636 close(pipe_fd[0]); | 617 close(pipe_fd[0]); |
637 | 618 |
638 // Always wait for exit code (even if we know we'll declare | 619 // Always wait for exit code (even if we know we'll declare |
639 // GOT_MAX_OUTPUT). | 620 // GOT_MAX_OUTPUT). |
640 Process process(pid); | 621 Process process(pid); |
641 bool success = process.WaitForExit(exit_code); | 622 bool success = process.WaitForExit(exit_code); |
Lei Zhang
2016/07/04 20:33:04
No need for a success variable. Just return.
benwells
2016/07/05 03:48:38
Done.
| |
642 | 623 |
643 // If we stopped because we read as much as we wanted, we return | 624 if (success) |
644 // GOT_MAX_OUTPUT (because the child may exit due to |SIGPIPE|). | 625 return true; |
645 if (!output_buf_left && bytes_read > 0) | 626 return false; |
646 return GOT_MAX_OUTPUT; | |
647 else if (success) | |
648 return EXECUTE_SUCCESS; | |
649 return EXECUTE_FAILURE; | |
650 } | 627 } |
651 } | 628 } |
652 } | 629 } |
653 | 630 |
654 bool GetAppOutput(const CommandLine& cl, std::string* output) { | 631 bool GetAppOutput(const CommandLine& cl, std::string* output) { |
655 return GetAppOutput(cl.argv(), output); | 632 return GetAppOutput(cl.argv(), output); |
656 } | 633 } |
657 | 634 |
658 bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) { | 635 bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) { |
659 // Run |execve()| with the current environment and store "unlimited" data. | 636 // Run |execve()| with the current environment and store "unlimited" data. |
660 int exit_code; | 637 int exit_code; |
661 GetAppOutputInternalResult result = GetAppOutputInternal( | 638 bool result = |
662 argv, NULL, false, output, std::numeric_limits<std::size_t>::max(), true, | 639 GetAppOutputInternal(argv, NULL, false, output, true, &exit_code); |
Lei Zhang
2016/07/04 20:33:04
Might as well s/NULL/nullptr/ while we are here.
benwells
2016/07/05 03:48:38
Done.
| |
663 &exit_code); | 640 return result && exit_code == EXIT_SUCCESS; |
664 return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS; | |
665 } | 641 } |
666 | 642 |
667 bool GetAppOutputAndError(const CommandLine& cl, std::string* output) { | 643 bool GetAppOutputAndError(const CommandLine& cl, std::string* output) { |
668 // Run |execve()| with the current environment and store "unlimited" data. | 644 // Run |execve()| with the current environment and store "unlimited" data. |
669 int exit_code; | 645 int exit_code; |
670 GetAppOutputInternalResult result = GetAppOutputInternal( | 646 bool result = |
671 cl.argv(), NULL, true, output, std::numeric_limits<std::size_t>::max(), | 647 GetAppOutputInternal(cl.argv(), NULL, true, output, true, &exit_code); |
672 true, &exit_code); | 648 return result && exit_code == EXIT_SUCCESS; |
673 return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS; | |
674 } | |
675 | |
676 // TODO(viettrungluu): Conceivably, we should have a timeout as well, so we | |
677 // don't hang if what we're calling hangs. | |
678 bool GetAppOutputRestricted(const CommandLine& cl, | |
679 std::string* output, size_t max_output) { | |
680 // Run |execve()| with the empty environment. | |
681 char* const empty_environ = NULL; | |
682 int exit_code; | |
683 GetAppOutputInternalResult result = GetAppOutputInternal( | |
684 cl.argv(), &empty_environ, false, output, max_output, false, &exit_code); | |
685 return result == GOT_MAX_OUTPUT || (result == EXECUTE_SUCCESS && | |
686 exit_code == EXIT_SUCCESS); | |
687 } | 649 } |
688 | 650 |
689 bool GetAppOutputWithExitCode(const CommandLine& cl, | 651 bool GetAppOutputWithExitCode(const CommandLine& cl, |
690 std::string* output, | 652 std::string* output, |
691 int* exit_code) { | 653 int* exit_code) { |
692 // Run |execve()| with the current environment and store "unlimited" data. | 654 // Run |execve()| with the current environment and store "unlimited" data. |
693 GetAppOutputInternalResult result = GetAppOutputInternal( | 655 return GetAppOutputInternal(cl.argv(), NULL, false, output, true, exit_code); |
694 cl.argv(), NULL, false, output, std::numeric_limits<std::size_t>::max(), | |
695 true, exit_code); | |
696 return result == EXECUTE_SUCCESS; | |
697 } | 656 } |
698 | 657 |
699 #endif // !defined(OS_NACL_NONSFI) | 658 #endif // !defined(OS_NACL_NONSFI) |
700 | 659 |
701 #if defined(OS_LINUX) || defined(OS_NACL_NONSFI) | 660 #if defined(OS_LINUX) || defined(OS_NACL_NONSFI) |
702 namespace { | 661 namespace { |
703 | 662 |
704 bool IsRunningOnValgrind() { | 663 bool IsRunningOnValgrind() { |
705 return RUNNING_ON_VALGRIND; | 664 return RUNNING_ON_VALGRIND; |
706 } | 665 } |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
783 jmp_buf env; | 742 jmp_buf env; |
784 if (setjmp(env) == 0) { | 743 if (setjmp(env) == 0) { |
785 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); | 744 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); |
786 } | 745 } |
787 | 746 |
788 return 0; | 747 return 0; |
789 } | 748 } |
790 #endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI) | 749 #endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI) |
791 | 750 |
792 } // namespace base | 751 } // namespace base |
OLD | NEW |