| 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 |