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 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 EXECUTE_FAILURE, | 523 EXECUTE_FAILURE, |
524 EXECUTE_SUCCESS, | 524 EXECUTE_SUCCESS, |
525 GOT_MAX_OUTPUT, | 525 GOT_MAX_OUTPUT, |
526 }; | 526 }; |
527 | 527 |
528 // Executes the application specified by |argv| and wait for it to exit. Stores | 528 // Executes the application specified by |argv| and wait for it to exit. Stores |
529 // the output (stdout) in |output|. If |do_search_path| is set, it searches the | 529 // the output (stdout) in |output|. If |do_search_path| is set, it searches the |
530 // path for the application; in that case, |envp| must be null, and it will use | 530 // path for the application; in that case, |envp| must be null, and it will use |
531 // the current environment. If |do_search_path| is false, |argv[0]| should fully | 531 // the current environment. If |do_search_path| is false, |argv[0]| should fully |
532 // specify the path of the application, and |envp| will be used as the | 532 // specify the path of the application, and |envp| will be used as the |
533 // environment. Redirects stderr to /dev/null. | 533 // environment. If |include_stderr| is true, includes stderr otherwise redirects |
| 534 // it to /dev/null. |
534 // If we successfully start the application and get all requested output, we | 535 // If we successfully start the application and get all requested output, we |
535 // return GOT_MAX_OUTPUT, or if there is a problem starting or exiting | 536 // return GOT_MAX_OUTPUT, or if there is a problem starting or exiting |
536 // the application we return RUN_FAILURE. Otherwise we return EXECUTE_SUCCESS. | 537 // the application we return RUN_FAILURE. Otherwise we return EXECUTE_SUCCESS. |
537 // The GOT_MAX_OUTPUT return value exists so a caller that asks for limited | 538 // The GOT_MAX_OUTPUT return value exists so a caller that asks for limited |
538 // output can treat this as a success, despite having an exit code of SIG_PIPE | 539 // output can treat this as a success, despite having an exit code of SIG_PIPE |
539 // due to us closing the output pipe. | 540 // due to us closing the output pipe. |
540 // In the case of EXECUTE_SUCCESS, the application exit code will be returned | 541 // In the case of EXECUTE_SUCCESS, the application exit code will be returned |
541 // in |*exit_code|, which should be checked to determine if the application | 542 // in |*exit_code|, which should be checked to determine if the application |
542 // ran successfully. | 543 // ran successfully. |
543 static GetAppOutputInternalResult GetAppOutputInternal( | 544 static GetAppOutputInternalResult GetAppOutputInternal( |
544 const std::vector<std::string>& argv, | 545 const std::vector<std::string>& argv, |
545 char* const envp[], | 546 char* const envp[], |
| 547 bool include_stderr, |
546 std::string* output, | 548 std::string* output, |
547 size_t max_output, | 549 size_t max_output, |
548 bool do_search_path, | 550 bool do_search_path, |
549 int* exit_code) { | 551 int* exit_code) { |
550 // Doing a blocking wait for another command to finish counts as IO. | 552 // Doing a blocking wait for another command to finish counts as IO. |
551 base::ThreadRestrictions::AssertIOAllowed(); | 553 base::ThreadRestrictions::AssertIOAllowed(); |
552 // exit_code must be supplied so calling function can determine success. | 554 // exit_code must be supplied so calling function can determine success. |
553 DCHECK(exit_code); | 555 DCHECK(exit_code); |
554 *exit_code = EXIT_FAILURE; | 556 *exit_code = EXIT_FAILURE; |
555 | 557 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 int dev_null = open("/dev/null", O_WRONLY); | 592 int dev_null = open("/dev/null", O_WRONLY); |
591 if (dev_null < 0) | 593 if (dev_null < 0) |
592 _exit(127); | 594 _exit(127); |
593 | 595 |
594 // Stop type-profiler. | 596 // Stop type-profiler. |
595 // The profiler should be stopped between fork and exec since it inserts | 597 // The profiler should be stopped between fork and exec since it inserts |
596 // locks at new/delete expressions. See http://crbug.com/36678. | 598 // locks at new/delete expressions. See http://crbug.com/36678. |
597 base::type_profiler::Controller::Stop(); | 599 base::type_profiler::Controller::Stop(); |
598 | 600 |
599 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); | 601 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); |
600 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); | 602 fd_shuffle1.push_back(InjectionArc( |
| 603 include_stderr ? pipe_fd[1] : dev_null, |
| 604 STDERR_FILENO, true)); |
601 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); | 605 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); |
602 // Adding another element here? Remeber to increase the argument to | 606 // Adding another element here? Remeber to increase the argument to |
603 // reserve(), above. | 607 // reserve(), above. |
604 | 608 |
605 for (size_t i = 0; i < fd_shuffle1.size(); ++i) | 609 for (size_t i = 0; i < fd_shuffle1.size(); ++i) |
606 fd_shuffle2.push_back(fd_shuffle1[i]); | 610 fd_shuffle2.push_back(fd_shuffle1[i]); |
607 | 611 |
608 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 612 if (!ShuffleFileDescriptors(&fd_shuffle1)) |
609 _exit(127); | 613 _exit(127); |
610 | 614 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 } | 663 } |
660 | 664 |
661 bool GetAppOutput(const CommandLine& cl, std::string* output) { | 665 bool GetAppOutput(const CommandLine& cl, std::string* output) { |
662 return GetAppOutput(cl.argv(), output); | 666 return GetAppOutput(cl.argv(), output); |
663 } | 667 } |
664 | 668 |
665 bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) { | 669 bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) { |
666 // Run |execve()| with the current environment and store "unlimited" data. | 670 // Run |execve()| with the current environment and store "unlimited" data. |
667 int exit_code; | 671 int exit_code; |
668 GetAppOutputInternalResult result = GetAppOutputInternal( | 672 GetAppOutputInternalResult result = GetAppOutputInternal( |
669 argv, NULL, output, std::numeric_limits<std::size_t>::max(), true, | 673 argv, NULL, false, output, std::numeric_limits<std::size_t>::max(), true, |
670 &exit_code); | 674 &exit_code); |
671 return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS; | 675 return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS; |
672 } | 676 } |
673 | 677 |
| 678 bool GetAppOutputAndError(const CommandLine& cl, std::string* output) { |
| 679 // Run |execve()| with the current environment and store "unlimited" data. |
| 680 int exit_code; |
| 681 GetAppOutputInternalResult result = GetAppOutputInternal( |
| 682 cl.argv(), NULL, true, output, std::numeric_limits<std::size_t>::max(), |
| 683 true, &exit_code); |
| 684 return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS; |
| 685 } |
| 686 |
674 // TODO(viettrungluu): Conceivably, we should have a timeout as well, so we | 687 // TODO(viettrungluu): Conceivably, we should have a timeout as well, so we |
675 // don't hang if what we're calling hangs. | 688 // don't hang if what we're calling hangs. |
676 bool GetAppOutputRestricted(const CommandLine& cl, | 689 bool GetAppOutputRestricted(const CommandLine& cl, |
677 std::string* output, size_t max_output) { | 690 std::string* output, size_t max_output) { |
678 // Run |execve()| with the empty environment. | 691 // Run |execve()| with the empty environment. |
679 char* const empty_environ = NULL; | 692 char* const empty_environ = NULL; |
680 int exit_code; | 693 int exit_code; |
681 GetAppOutputInternalResult result = GetAppOutputInternal( | 694 GetAppOutputInternalResult result = GetAppOutputInternal( |
682 cl.argv(), &empty_environ, output, max_output, false, &exit_code); | 695 cl.argv(), &empty_environ, false, output, max_output, false, &exit_code); |
683 return result == GOT_MAX_OUTPUT || (result == EXECUTE_SUCCESS && | 696 return result == GOT_MAX_OUTPUT || (result == EXECUTE_SUCCESS && |
684 exit_code == EXIT_SUCCESS); | 697 exit_code == EXIT_SUCCESS); |
685 } | 698 } |
686 | 699 |
687 bool GetAppOutputWithExitCode(const CommandLine& cl, | 700 bool GetAppOutputWithExitCode(const CommandLine& cl, |
688 std::string* output, | 701 std::string* output, |
689 int* exit_code) { | 702 int* exit_code) { |
690 // Run |execve()| with the current environment and store "unlimited" data. | 703 // Run |execve()| with the current environment and store "unlimited" data. |
691 GetAppOutputInternalResult result = GetAppOutputInternal( | 704 GetAppOutputInternalResult result = GetAppOutputInternal( |
692 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, | 705 cl.argv(), NULL, false, output, std::numeric_limits<std::size_t>::max(), |
693 exit_code); | 706 true, exit_code); |
694 return result == EXECUTE_SUCCESS; | 707 return result == EXECUTE_SUCCESS; |
695 } | 708 } |
696 | 709 |
697 #endif // !defined(OS_NACL_NONSFI) | 710 #endif // !defined(OS_NACL_NONSFI) |
698 | 711 |
699 #if defined(OS_LINUX) || defined(OS_NACL_NONSFI) | 712 #if defined(OS_LINUX) || defined(OS_NACL_NONSFI) |
700 namespace { | 713 namespace { |
701 | 714 |
702 bool IsRunningOnValgrind() { | 715 bool IsRunningOnValgrind() { |
703 return RUNNING_ON_VALGRIND; | 716 return RUNNING_ON_VALGRIND; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 jmp_buf env; | 794 jmp_buf env; |
782 if (setjmp(env) == 0) { | 795 if (setjmp(env) == 0) { |
783 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); | 796 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); |
784 } | 797 } |
785 | 798 |
786 return 0; | 799 return 0; |
787 } | 800 } |
788 #endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI) | 801 #endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI) |
789 | 802 |
790 } // namespace base | 803 } // namespace base |
OLD | NEW |