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 <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 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 } | 597 } |
598 | 598 |
599 bool LaunchProcess(const std::vector<std::string>& argv, | 599 bool LaunchProcess(const std::vector<std::string>& argv, |
600 const LaunchOptions& options, | 600 const LaunchOptions& options, |
601 ProcessHandle* process_handle) { | 601 ProcessHandle* process_handle) { |
602 size_t fd_shuffle_size = 0; | 602 size_t fd_shuffle_size = 0; |
603 if (options.fds_to_remap) { | 603 if (options.fds_to_remap) { |
604 fd_shuffle_size = options.fds_to_remap->size(); | 604 fd_shuffle_size = options.fds_to_remap->size(); |
605 } | 605 } |
606 | 606 |
607 #if defined(OS_MACOSX) | |
608 if (options.synchronize) { | |
609 // When synchronizing, the "read" end of the synchronization pipe needs | |
610 // to make it to the child process. This is handled by mapping it back to | |
611 // itself. | |
612 ++fd_shuffle_size; | |
613 } | |
614 #endif // defined(OS_MACOSX) | |
615 | |
616 InjectiveMultimap fd_shuffle1; | 607 InjectiveMultimap fd_shuffle1; |
617 InjectiveMultimap fd_shuffle2; | 608 InjectiveMultimap fd_shuffle2; |
618 fd_shuffle1.reserve(fd_shuffle_size); | 609 fd_shuffle1.reserve(fd_shuffle_size); |
619 fd_shuffle2.reserve(fd_shuffle_size); | 610 fd_shuffle2.reserve(fd_shuffle_size); |
620 | 611 |
621 scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]); | 612 scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]); |
622 scoped_ptr<char*[]> new_environ; | 613 scoped_ptr<char*[]> new_environ; |
623 if (options.environ) | 614 if (options.environ) |
624 new_environ.reset(AlterEnvironment(*options.environ, GetEnvironment())); | 615 new_environ.reset(AlterEnvironment(*options.environ, GetEnvironment())); |
625 | 616 |
626 #if defined(OS_MACOSX) | |
627 int synchronization_pipe_fds[2]; | |
628 file_util::ScopedFD synchronization_read_fd; | |
629 file_util::ScopedFD synchronization_write_fd; | |
630 | |
631 if (options.synchronize) { | |
632 // wait means "don't return from LaunchProcess until the child exits", and | |
633 // synchronize means "return from LaunchProcess but don't let the child | |
634 // run until LaunchSynchronize is called". These two options are highly | |
635 // incompatible. | |
636 DCHECK(!options.wait); | |
637 | |
638 // Create the pipe used for synchronization. | |
639 if (HANDLE_EINTR(pipe(synchronization_pipe_fds)) != 0) { | |
640 DPLOG(ERROR) << "pipe"; | |
641 return false; | |
642 } | |
643 | |
644 // The parent process will only use synchronization_write_fd as the write | |
645 // side of the pipe. It can close the read side as soon as the child | |
646 // process has forked off. The child process will only use | |
647 // synchronization_read_fd as the read side of the pipe. In that process, | |
648 // the write side can be closed as soon as it has forked. | |
649 synchronization_read_fd.reset(&synchronization_pipe_fds[0]); | |
650 synchronization_write_fd.reset(&synchronization_pipe_fds[1]); | |
651 } | |
652 #endif // OS_MACOSX | |
653 | |
654 pid_t pid; | 617 pid_t pid; |
655 #if defined(OS_LINUX) | 618 #if defined(OS_LINUX) |
656 if (options.clone_flags) { | 619 if (options.clone_flags) { |
657 pid = syscall(__NR_clone, options.clone_flags, 0, 0, 0); | 620 pid = syscall(__NR_clone, options.clone_flags, 0, 0, 0); |
658 } else | 621 } else |
659 #endif | 622 #endif |
660 { | 623 { |
661 pid = fork(); | 624 pid = fork(); |
662 } | 625 } |
663 | 626 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 #if defined(OS_MACOSX) | 699 #if defined(OS_MACOSX) |
737 RestoreDefaultExceptionHandler(); | 700 RestoreDefaultExceptionHandler(); |
738 #endif // defined(OS_MACOSX) | 701 #endif // defined(OS_MACOSX) |
739 | 702 |
740 ResetChildSignalHandlersToDefaults(); | 703 ResetChildSignalHandlersToDefaults(); |
741 | 704 |
742 if (options.debug) { | 705 if (options.debug) { |
743 RAW_LOG(INFO, "Right after signal/exception handler restoration."); | 706 RAW_LOG(INFO, "Right after signal/exception handler restoration."); |
744 } | 707 } |
745 | 708 |
746 #if defined(OS_MACOSX) | |
747 if (options.synchronize) { | |
748 // The "write" side of the synchronization pipe belongs to the parent. | |
749 synchronization_write_fd.reset(); // closes synchronization_pipe_fds[1] | |
750 } | |
751 #endif // defined(OS_MACOSX) | |
752 | |
753 #if 0 | 709 #if 0 |
754 // When debugging it can be helpful to check that we really aren't making | 710 // When debugging it can be helpful to check that we really aren't making |
755 // any hidden calls to malloc. | 711 // any hidden calls to malloc. |
756 void *malloc_thunk = | 712 void *malloc_thunk = |
757 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); | 713 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); |
758 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); | 714 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); |
759 memset(reinterpret_cast<void*>(malloc), 0xff, 8); | 715 memset(reinterpret_cast<void*>(malloc), 0xff, 8); |
760 #endif // 0 | 716 #endif // 0 |
761 | 717 |
762 // DANGER: no calls to malloc are allowed from now on: | 718 // DANGER: no calls to malloc are allowed from now on: |
(...skipping 19 matching lines...) Expand all Loading... |
782 it != options.fds_to_remap->end(); ++it) { | 738 it != options.fds_to_remap->end(); ++it) { |
783 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); | 739 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); |
784 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); | 740 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); |
785 } | 741 } |
786 } | 742 } |
787 | 743 |
788 if (options.debug) { | 744 if (options.debug) { |
789 RAW_LOG(INFO, "Right after fd_shuffle push_backs."); | 745 RAW_LOG(INFO, "Right after fd_shuffle push_backs."); |
790 } | 746 } |
791 | 747 |
792 #if defined(OS_MACOSX) | |
793 if (options.synchronize) { | |
794 // Remap the read side of the synchronization pipe back onto itself, | |
795 // ensuring that it won't be closed by CloseSuperfluousFds. | |
796 int keep_fd = *synchronization_read_fd.get(); | |
797 fd_shuffle1.push_back(InjectionArc(keep_fd, keep_fd, false)); | |
798 fd_shuffle2.push_back(InjectionArc(keep_fd, keep_fd, false)); | |
799 } | |
800 #endif // defined(OS_MACOSX) | |
801 | |
802 if (options.environ) | 748 if (options.environ) |
803 SetEnvironment(new_environ.get()); | 749 SetEnvironment(new_environ.get()); |
804 | 750 |
805 // fd_shuffle1 is mutated by this call because it cannot malloc. | 751 // fd_shuffle1 is mutated by this call because it cannot malloc. |
806 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 752 if (!ShuffleFileDescriptors(&fd_shuffle1)) |
807 _exit(127); | 753 _exit(127); |
808 | 754 |
809 if (options.debug) { | 755 if (options.debug) { |
810 RAW_LOG(INFO, "Right after ShuffleFileDescriptors"); | 756 RAW_LOG(INFO, "Right after ShuffleFileDescriptors"); |
811 } | 757 } |
812 | 758 |
813 CloseSuperfluousFds(fd_shuffle2); | 759 CloseSuperfluousFds(fd_shuffle2); |
814 | 760 |
815 if (options.debug) { | 761 if (options.debug) { |
816 RAW_LOG(INFO, "Right after CloseSuperfluousFds"); | 762 RAW_LOG(INFO, "Right after CloseSuperfluousFds"); |
817 } | 763 } |
818 | 764 |
819 #if defined(OS_MACOSX) | |
820 if (options.synchronize) { | |
821 // Do a blocking read to wait until the parent says it's OK to proceed. | |
822 // The byte that's read here is written by LaunchSynchronize. | |
823 char read_char; | |
824 int read_result = | |
825 HANDLE_EINTR(read(*synchronization_read_fd.get(), &read_char, 1)); | |
826 if (read_result != 1) { | |
827 RAW_LOG(ERROR, "LaunchProcess: synchronization read: error"); | |
828 _exit(127); | |
829 } | |
830 | |
831 // The pipe is no longer useful. Don't let it live on in the new process | |
832 // after exec. | |
833 synchronization_read_fd.reset(); // closes synchronization_pipe_fds[0] | |
834 } | |
835 #endif // defined(OS_MACOSX) | |
836 | |
837 if (options.debug) { | 765 if (options.debug) { |
838 RAW_LOG(INFO, "Right before execvp"); | 766 RAW_LOG(INFO, "Right before execvp"); |
839 } | 767 } |
840 | 768 |
841 for (size_t i = 0; i < argv.size(); i++) | 769 for (size_t i = 0; i < argv.size(); i++) |
842 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 770 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
843 argv_cstr[argv.size()] = NULL; | 771 argv_cstr[argv.size()] = NULL; |
844 execvp(argv_cstr[0], argv_cstr.get()); | 772 execvp(argv_cstr[0], argv_cstr.get()); |
845 | 773 |
846 RAW_LOG(ERROR, "LaunchProcess: failed to execvp:"); | 774 RAW_LOG(ERROR, "LaunchProcess: failed to execvp:"); |
847 RAW_LOG(ERROR, argv_cstr[0]); | 775 RAW_LOG(ERROR, argv_cstr[0]); |
848 _exit(127); | 776 _exit(127); |
849 } else { | 777 } else { |
850 // Parent process | 778 // Parent process |
851 if (options.wait) { | 779 if (options.wait) { |
852 // While this isn't strictly disk IO, waiting for another process to | 780 // While this isn't strictly disk IO, waiting for another process to |
853 // finish is the sort of thing ThreadRestrictions is trying to prevent. | 781 // finish is the sort of thing ThreadRestrictions is trying to prevent. |
854 base::ThreadRestrictions::AssertIOAllowed(); | 782 base::ThreadRestrictions::AssertIOAllowed(); |
855 pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0)); | 783 pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0)); |
856 DPCHECK(ret > 0); | 784 DPCHECK(ret > 0); |
857 } | 785 } |
858 | 786 |
859 if (process_handle) | 787 if (process_handle) |
860 *process_handle = pid; | 788 *process_handle = pid; |
861 | |
862 #if defined(OS_MACOSX) | |
863 if (options.synchronize) { | |
864 // The "read" side of the synchronization pipe belongs to the child. | |
865 synchronization_read_fd.reset(); // closes synchronization_pipe_fds[0] | |
866 *options.synchronize = new int(*synchronization_write_fd.release()); | |
867 } | |
868 #endif // defined(OS_MACOSX) | |
869 } | 789 } |
870 | 790 |
871 return true; | 791 return true; |
872 } | 792 } |
873 | 793 |
874 | 794 |
875 bool LaunchProcess(const CommandLine& cmdline, | 795 bool LaunchProcess(const CommandLine& cmdline, |
876 const LaunchOptions& options, | 796 const LaunchOptions& options, |
877 ProcessHandle* process_handle) { | 797 ProcessHandle* process_handle) { |
878 return LaunchProcess(cmdline.argv(), options, process_handle); | 798 return LaunchProcess(cmdline.argv(), options, process_handle); |
879 } | 799 } |
880 | 800 |
881 #if defined(OS_MACOSX) | |
882 void LaunchSynchronize(LaunchSynchronizationHandle handle) { | |
883 int synchronization_fd = *handle; | |
884 file_util::ScopedFD synchronization_fd_closer(&synchronization_fd); | |
885 delete handle; | |
886 | |
887 // Write a '\0' character to the pipe. | |
888 if (HANDLE_EINTR(write(synchronization_fd, "", 1)) != 1) { | |
889 DPLOG(ERROR) << "write"; | |
890 } | |
891 } | |
892 #endif // defined(OS_MACOSX) | |
893 | |
894 ProcessMetrics::~ProcessMetrics() { } | 801 ProcessMetrics::~ProcessMetrics() { } |
895 | 802 |
896 void RaiseProcessToHighPriority() { | 803 void RaiseProcessToHighPriority() { |
897 // On POSIX, we don't actually do anything here. We could try to nice() or | 804 // On POSIX, we don't actually do anything here. We could try to nice() or |
898 // setpriority() or sched_getscheduler, but these all require extra rights. | 805 // setpriority() or sched_getscheduler, but these all require extra rights. |
899 } | 806 } |
900 | 807 |
901 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) { | 808 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) { |
902 return GetTerminationStatusImpl(handle, false /* can_block */, exit_code); | 809 return GetTerminationStatusImpl(handle, false /* can_block */, exit_code); |
903 } | 810 } |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1372 if (IsChildDead(process)) | 1279 if (IsChildDead(process)) |
1373 return; | 1280 return; |
1374 | 1281 |
1375 BackgroundReaper* reaper = new BackgroundReaper(process, 0); | 1282 BackgroundReaper* reaper = new BackgroundReaper(process, 0); |
1376 PlatformThread::CreateNonJoinable(0, reaper); | 1283 PlatformThread::CreateNonJoinable(0, reaper); |
1377 } | 1284 } |
1378 | 1285 |
1379 #endif // !defined(OS_MACOSX) | 1286 #endif // !defined(OS_MACOSX) |
1380 | 1287 |
1381 } // namespace base | 1288 } // namespace base |
OLD | NEW |