| 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 15 matching lines...) Expand all Loading... |
| 26 #include "base/files/dir_reader_posix.h" | 26 #include "base/files/dir_reader_posix.h" |
| 27 #include "base/logging.h" | 27 #include "base/logging.h" |
| 28 #include "base/memory/scoped_ptr.h" | 28 #include "base/memory/scoped_ptr.h" |
| 29 #include "base/process_util.h" | 29 #include "base/process_util.h" |
| 30 #include "base/stringprintf.h" | 30 #include "base/stringprintf.h" |
| 31 #include "base/synchronization/waitable_event.h" | 31 #include "base/synchronization/waitable_event.h" |
| 32 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 32 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
| 33 #include "base/threading/platform_thread.h" | 33 #include "base/threading/platform_thread.h" |
| 34 #include "base/threading/thread_restrictions.h" | 34 #include "base/threading/thread_restrictions.h" |
| 35 | 35 |
| 36 // TODO(dmikurube): Consider always calling {Suspend|Resume}AllocatedType..., |
| 37 // and make them empty functions when !USE_ALLOCATED_TYPE. |
| 38 // This is a temporary comment which should be removed when landing. |
| 39 #ifdef USE_ALLOCATED_TYPE |
| 40 #include "base/allocator/allocated_type_tcmalloc.h" |
| 41 #endif |
| 42 |
| 36 #if defined(OS_CHROMEOS) | 43 #if defined(OS_CHROMEOS) |
| 37 #include <sys/ioctl.h> | 44 #include <sys/ioctl.h> |
| 38 #endif | 45 #endif |
| 39 | 46 |
| 40 #if defined(OS_FREEBSD) | 47 #if defined(OS_FREEBSD) |
| 41 #include <sys/event.h> | 48 #include <sys/event.h> |
| 42 #include <sys/ucontext.h> | 49 #include <sys/ucontext.h> |
| 43 #endif | 50 #endif |
| 44 | 51 |
| 45 #if defined(OS_MACOSX) | 52 #if defined(OS_MACOSX) |
| (...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 if (options.new_process_group) { | 641 if (options.new_process_group) { |
| 635 // Instead of inheriting the process group ID of the parent, the child | 642 // Instead of inheriting the process group ID of the parent, the child |
| 636 // starts off a new process group with pgid equal to its process ID. | 643 // starts off a new process group with pgid equal to its process ID. |
| 637 if (setpgid(0, 0) < 0) { | 644 if (setpgid(0, 0) < 0) { |
| 638 RAW_LOG(ERROR, "setpgid failed"); | 645 RAW_LOG(ERROR, "setpgid failed"); |
| 639 _exit(127); | 646 _exit(127); |
| 640 } | 647 } |
| 641 } | 648 } |
| 642 | 649 |
| 643 if (options.maximize_rlimits) { | 650 if (options.maximize_rlimits) { |
| 651 #ifdef USE_ALLOCATED_TYPE |
| 652 SuspendAllocatedTypeIntercept(); |
| 653 #endif |
| 644 // Some resource limits need to be maximal in this child. | 654 // Some resource limits need to be maximal in this child. |
| 645 std::set<int>::const_iterator resource; | 655 std::set<int>::const_iterator resource; |
| 646 for (resource = options.maximize_rlimits->begin(); | 656 for (resource = options.maximize_rlimits->begin(); |
| 647 resource != options.maximize_rlimits->end(); | 657 resource != options.maximize_rlimits->end(); |
| 648 ++resource) { | 658 ++resource) { |
| 649 struct rlimit limit; | 659 struct rlimit limit; |
| 650 if (getrlimit(*resource, &limit) < 0) { | 660 if (getrlimit(*resource, &limit) < 0) { |
| 651 RAW_LOG(WARNING, "getrlimit failed"); | 661 RAW_LOG(WARNING, "getrlimit failed"); |
| 652 } else if (limit.rlim_cur < limit.rlim_max) { | 662 } else if (limit.rlim_cur < limit.rlim_max) { |
| 653 limit.rlim_cur = limit.rlim_max; | 663 limit.rlim_cur = limit.rlim_max; |
| 654 if (setrlimit(*resource, &limit) < 0) { | 664 if (setrlimit(*resource, &limit) < 0) { |
| 655 RAW_LOG(WARNING, "setrlimit failed"); | 665 RAW_LOG(WARNING, "setrlimit failed"); |
| 656 } | 666 } |
| 657 } | 667 } |
| 658 } | 668 } |
| 669 #ifdef USE_ALLOCATED_TYPE |
| 670 ResumeAllocatedTypeIntercept(); |
| 671 #endif |
| 659 } | 672 } |
| 660 | 673 |
| 661 #if defined(OS_MACOSX) | 674 #if defined(OS_MACOSX) |
| 662 RestoreDefaultExceptionHandler(); | 675 RestoreDefaultExceptionHandler(); |
| 663 #endif // defined(OS_MACOSX) | 676 #endif // defined(OS_MACOSX) |
| 664 | 677 |
| 665 ResetChildSignalHandlersToDefaults(); | 678 ResetChildSignalHandlersToDefaults(); |
| 666 | 679 |
| 667 #if defined(OS_MACOSX) | 680 #if defined(OS_MACOSX) |
| 668 if (options.synchronize) { | 681 if (options.synchronize) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 691 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { | 704 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { |
| 692 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); | 705 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); |
| 693 } | 706 } |
| 694 } else { | 707 } else { |
| 695 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); | 708 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); |
| 696 } | 709 } |
| 697 } | 710 } |
| 698 #endif // defined(OS_CHROMEOS) | 711 #endif // defined(OS_CHROMEOS) |
| 699 | 712 |
| 700 if (options.fds_to_remap) { | 713 if (options.fds_to_remap) { |
| 714 #ifdef USE_ALLOCATED_TYPE |
| 715 SuspendAllocatedTypeIntercept(); |
| 716 #endif |
| 701 for (FileHandleMappingVector::const_iterator | 717 for (FileHandleMappingVector::const_iterator |
| 702 it = options.fds_to_remap->begin(); | 718 it = options.fds_to_remap->begin(); |
| 703 it != options.fds_to_remap->end(); ++it) { | 719 it != options.fds_to_remap->end(); ++it) { |
| 704 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); | 720 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); |
| 705 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); | 721 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); |
| 706 } | 722 } |
| 723 #ifdef USE_ALLOCATED_TYPE |
| 724 ResumeAllocatedTypeIntercept(); |
| 725 #endif |
| 707 } | 726 } |
| 708 | 727 |
| 709 #if defined(OS_MACOSX) | 728 #if defined(OS_MACOSX) |
| 710 if (options.synchronize) { | 729 if (options.synchronize) { |
| 730 #ifdef USE_ALLOCATED_TYPE |
| 731 SuspendAllocatedTypeIntercept(); |
| 732 #endif |
| 711 // Remap the read side of the synchronization pipe back onto itself, | 733 // Remap the read side of the synchronization pipe back onto itself, |
| 712 // ensuring that it won't be closed by CloseSuperfluousFds. | 734 // ensuring that it won't be closed by CloseSuperfluousFds. |
| 713 int keep_fd = *synchronization_read_fd.get(); | 735 int keep_fd = *synchronization_read_fd.get(); |
| 714 fd_shuffle1.push_back(InjectionArc(keep_fd, keep_fd, false)); | 736 fd_shuffle1.push_back(InjectionArc(keep_fd, keep_fd, false)); |
| 715 fd_shuffle2.push_back(InjectionArc(keep_fd, keep_fd, false)); | 737 fd_shuffle2.push_back(InjectionArc(keep_fd, keep_fd, false)); |
| 738 #ifdef USE_ALLOCATED_TYPE |
| 739 ResumeAllocatedTypeIntercept(); |
| 740 #endif |
| 716 } | 741 } |
| 717 #endif // defined(OS_MACOSX) | 742 #endif // defined(OS_MACOSX) |
| 718 | 743 |
| 719 if (options.environ) | 744 if (options.environ) |
| 720 SetEnvironment(new_environ.get()); | 745 SetEnvironment(new_environ.get()); |
| 721 | 746 |
| 747 #ifdef USE_ALLOCATED_TYPE |
| 748 SuspendAllocatedTypeIntercept(); |
| 749 #endif |
| 722 // fd_shuffle1 is mutated by this call because it cannot malloc. | 750 // fd_shuffle1 is mutated by this call because it cannot malloc. |
| 723 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 751 if (!ShuffleFileDescriptors(&fd_shuffle1)) { |
| 752 #ifdef USE_ALLOCATED_TYPE |
| 753 ResumeAllocatedTypeIntercept(); |
| 754 #endif |
| 724 _exit(127); | 755 _exit(127); |
| 756 } |
| 725 | 757 |
| 726 CloseSuperfluousFds(fd_shuffle2); | 758 CloseSuperfluousFds(fd_shuffle2); |
| 759 #ifdef USE_ALLOCATED_TYPE |
| 760 ResumeAllocatedTypeIntercept(); |
| 761 #endif |
| 727 | 762 |
| 728 #if defined(OS_MACOSX) | 763 #if defined(OS_MACOSX) |
| 729 if (options.synchronize) { | 764 if (options.synchronize) { |
| 730 // Do a blocking read to wait until the parent says it's OK to proceed. | 765 // Do a blocking read to wait until the parent says it's OK to proceed. |
| 731 // The byte that's read here is written by LaunchSynchronize. | 766 // The byte that's read here is written by LaunchSynchronize. |
| 732 char read_char; | 767 char read_char; |
| 733 int read_result = | 768 int read_result = |
| 734 HANDLE_EINTR(read(*synchronization_read_fd.get(), &read_char, 1)); | 769 HANDLE_EINTR(read(*synchronization_read_fd.get(), &read_char, 1)); |
| 735 if (read_result != 1) { | 770 if (read_result != 1) { |
| 736 RAW_LOG(ERROR, "LaunchProcess: synchronization read: error"); | 771 RAW_LOG(ERROR, "LaunchProcess: synchronization read: error"); |
| 737 _exit(127); | 772 _exit(127); |
| 738 } | 773 } |
| 739 | 774 |
| 740 // The pipe is no longer useful. Don't let it live on in the new process | 775 // The pipe is no longer useful. Don't let it live on in the new process |
| 741 // after exec. | 776 // after exec. |
| 742 synchronization_read_fd.reset(); // closes synchronization_pipe_fds[0] | 777 synchronization_read_fd.reset(); // closes synchronization_pipe_fds[0] |
| 743 } | 778 } |
| 744 #endif // defined(OS_MACOSX) | 779 #endif // defined(OS_MACOSX) |
| 745 | 780 |
| 781 #ifdef USE_ALLOCATED_TYPE |
| 782 SuspendAllocatedTypeIntercept(); |
| 783 #endif |
| 746 for (size_t i = 0; i < argv.size(); i++) | 784 for (size_t i = 0; i < argv.size(); i++) |
| 747 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 785 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
| 748 argv_cstr[argv.size()] = NULL; | 786 argv_cstr[argv.size()] = NULL; |
| 787 #ifdef USE_ALLOCATED_TYPE |
| 788 // TODO(dmikurube): Consider removing it. It's just befor exec. |
| 789 // This is a temporary comment which should be removed when landing. |
| 790 ResumeAllocatedTypeIntercept(); |
| 791 #endif |
| 749 execvp(argv_cstr[0], argv_cstr.get()); | 792 execvp(argv_cstr[0], argv_cstr.get()); |
| 750 | 793 |
| 751 RAW_LOG(ERROR, "LaunchProcess: failed to execvp:"); | 794 RAW_LOG(ERROR, "LaunchProcess: failed to execvp:"); |
| 752 RAW_LOG(ERROR, argv_cstr[0]); | 795 RAW_LOG(ERROR, argv_cstr[0]); |
| 753 _exit(127); | 796 _exit(127); |
| 754 } else { | 797 } else { |
| 755 // Parent process | 798 // Parent process |
| 756 if (options.wait) { | 799 if (options.wait) { |
| 757 // While this isn't strictly disk IO, waiting for another process to | 800 // While this isn't strictly disk IO, waiting for another process to |
| 758 // finish is the sort of thing ThreadRestrictions is trying to prevent. | 801 // finish is the sort of thing ThreadRestrictions is trying to prevent. |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1101 | 1144 |
| 1102 // Obscure fork() rule: in the child, if you don't end up doing exec*(), | 1145 // Obscure fork() rule: in the child, if you don't end up doing exec*(), |
| 1103 // you call _exit() instead of exit(). This is because _exit() does not | 1146 // you call _exit() instead of exit(). This is because _exit() does not |
| 1104 // call any previously-registered (in the parent) exit handlers, which | 1147 // call any previously-registered (in the parent) exit handlers, which |
| 1105 // might do things like block waiting for threads that don't even exist | 1148 // might do things like block waiting for threads that don't even exist |
| 1106 // in the child. | 1149 // in the child. |
| 1107 int dev_null = open("/dev/null", O_WRONLY); | 1150 int dev_null = open("/dev/null", O_WRONLY); |
| 1108 if (dev_null < 0) | 1151 if (dev_null < 0) |
| 1109 _exit(127); | 1152 _exit(127); |
| 1110 | 1153 |
| 1154 #ifdef USE_ALLOCATED_TYPE |
| 1155 SuspendAllocatedTypeIntercept(); |
| 1156 #endif |
| 1111 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); | 1157 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); |
| 1112 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); | 1158 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); |
| 1113 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); | 1159 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); |
| 1114 // Adding another element here? Remeber to increase the argument to | 1160 // Adding another element here? Remeber to increase the argument to |
| 1115 // reserve(), above. | 1161 // reserve(), above. |
| 1116 | 1162 |
| 1117 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(), | 1163 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(), |
| 1118 std::back_inserter(fd_shuffle2)); | 1164 std::back_inserter(fd_shuffle2)); |
| 1119 | 1165 |
| 1120 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 1166 if (!ShuffleFileDescriptors(&fd_shuffle1)) { |
| 1167 #ifdef USE_ALLOCATED_TYPE |
| 1168 ResumeAllocatedTypeIntercept(); |
| 1169 #endif |
| 1121 _exit(127); | 1170 _exit(127); |
| 1171 } |
| 1122 | 1172 |
| 1123 CloseSuperfluousFds(fd_shuffle2); | 1173 CloseSuperfluousFds(fd_shuffle2); |
| 1124 | 1174 |
| 1125 for (size_t i = 0; i < argv.size(); i++) | 1175 for (size_t i = 0; i < argv.size(); i++) |
| 1126 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 1176 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
| 1127 argv_cstr[argv.size()] = NULL; | 1177 argv_cstr[argv.size()] = NULL; |
| 1178 #ifdef USE_ALLOCATED_TYPE |
| 1179 // TODO(dmikurube): Consider removing it. It's just befor exec. |
| 1180 // This is a temporary comment which should be removed when landing. |
| 1181 ResumeAllocatedTypeIntercept(); |
| 1182 #endif |
| 1128 if (do_search_path) | 1183 if (do_search_path) |
| 1129 execvp(argv_cstr[0], argv_cstr.get()); | 1184 execvp(argv_cstr[0], argv_cstr.get()); |
| 1130 else | 1185 else |
| 1131 execve(argv_cstr[0], argv_cstr.get(), envp); | 1186 execve(argv_cstr[0], argv_cstr.get(), envp); |
| 1132 _exit(127); | 1187 _exit(127); |
| 1133 } | 1188 } |
| 1134 default: // parent | 1189 default: // parent |
| 1135 { | 1190 { |
| 1136 // Close our writing end of pipe now. Otherwise later read would not | 1191 // Close our writing end of pipe now. Otherwise later read would not |
| 1137 // be able to detect end of child's output (in theory we could still | 1192 // be able to detect end of child's output (in theory we could still |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1328 if (IsChildDead(process)) | 1383 if (IsChildDead(process)) |
| 1329 return; | 1384 return; |
| 1330 | 1385 |
| 1331 BackgroundReaper* reaper = new BackgroundReaper(process, 0); | 1386 BackgroundReaper* reaper = new BackgroundReaper(process, 0); |
| 1332 PlatformThread::CreateNonJoinable(0, reaper); | 1387 PlatformThread::CreateNonJoinable(0, reaper); |
| 1333 } | 1388 } |
| 1334 | 1389 |
| 1335 #endif // !defined(OS_MACOSX) | 1390 #endif // !defined(OS_MACOSX) |
| 1336 | 1391 |
| 1337 } // namespace base | 1392 } // namespace base |
| OLD | NEW |