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 |