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 #ifdef USE_ALLOCATED_TYPE | |
37 #include "base/allocator/allocated_type_tcmalloc.h" | |
38 #endif | |
39 | |
36 #if defined(OS_CHROMEOS) | 40 #if defined(OS_CHROMEOS) |
37 #include <sys/ioctl.h> | 41 #include <sys/ioctl.h> |
38 #endif | 42 #endif |
39 | 43 |
40 #if defined(OS_FREEBSD) | 44 #if defined(OS_FREEBSD) |
41 #include <sys/event.h> | 45 #include <sys/event.h> |
42 #include <sys/ucontext.h> | 46 #include <sys/ucontext.h> |
43 #endif | 47 #endif |
44 | 48 |
45 #if defined(OS_MACOSX) | 49 #if defined(OS_MACOSX) |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
634 if (options.new_process_group) { | 638 if (options.new_process_group) { |
635 // Instead of inheriting the process group ID of the parent, the child | 639 // 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. | 640 // starts off a new process group with pgid equal to its process ID. |
637 if (setpgid(0, 0) < 0) { | 641 if (setpgid(0, 0) < 0) { |
638 RAW_LOG(ERROR, "setpgid failed"); | 642 RAW_LOG(ERROR, "setpgid failed"); |
639 _exit(127); | 643 _exit(127); |
640 } | 644 } |
641 } | 645 } |
642 | 646 |
643 if (options.maximize_rlimits) { | 647 if (options.maximize_rlimits) { |
648 #ifdef USE_ALLOCATED_TYPE | |
649 SuspendAllocatedTypeIntercept(); | |
650 #endif | |
Dai Mikurube (NOT FULLTIME)
2012/08/02 07:43:55
These are to avoid the DANGER of http://crbug.com/
Nico
2012/08/02 15:35:03
As far as I understand the bug, any code that does
Dai Mikurube (NOT FULLTIME)
2012/08/02 16:14:35
In my understanding, they don't allocate (malloc)
jar (doing other things)
2012/08/02 23:38:30
I don't follow this motivation.
...but... if your
Dai Mikurube (NOT FULLTIME)
2012/08/03 10:01:50
Thank you. That is a good idea.
For now, I keep
jar (doing other things)
2012/08/04 01:13:47
Your original comment was "...unreadable. It is ba
Dai Mikurube (NOT FULLTIME)
2012/08/07 10:39:18
I'm still thinking also about removing all STL ope
| |
644 // Some resource limits need to be maximal in this child. | 651 // Some resource limits need to be maximal in this child. |
645 std::set<int>::const_iterator resource; | 652 std::set<int>::const_iterator resource; |
646 for (resource = options.maximize_rlimits->begin(); | 653 for (resource = options.maximize_rlimits->begin(); |
647 resource != options.maximize_rlimits->end(); | 654 resource != options.maximize_rlimits->end(); |
648 ++resource) { | 655 ++resource) { |
649 struct rlimit limit; | 656 struct rlimit limit; |
650 if (getrlimit(*resource, &limit) < 0) { | 657 if (getrlimit(*resource, &limit) < 0) { |
651 RAW_LOG(WARNING, "getrlimit failed"); | 658 RAW_LOG(WARNING, "getrlimit failed"); |
652 } else if (limit.rlim_cur < limit.rlim_max) { | 659 } else if (limit.rlim_cur < limit.rlim_max) { |
653 limit.rlim_cur = limit.rlim_max; | 660 limit.rlim_cur = limit.rlim_max; |
654 if (setrlimit(*resource, &limit) < 0) { | 661 if (setrlimit(*resource, &limit) < 0) { |
655 RAW_LOG(WARNING, "setrlimit failed"); | 662 RAW_LOG(WARNING, "setrlimit failed"); |
656 } | 663 } |
657 } | 664 } |
658 } | 665 } |
666 #ifdef USE_ALLOCATED_TYPE | |
667 ResumeAllocatedTypeIntercept(); | |
668 #endif | |
659 } | 669 } |
660 | 670 |
661 #if defined(OS_MACOSX) | 671 #if defined(OS_MACOSX) |
662 RestoreDefaultExceptionHandler(); | 672 RestoreDefaultExceptionHandler(); |
663 #endif // defined(OS_MACOSX) | 673 #endif // defined(OS_MACOSX) |
664 | 674 |
665 ResetChildSignalHandlersToDefaults(); | 675 ResetChildSignalHandlersToDefaults(); |
666 | 676 |
667 #if defined(OS_MACOSX) | 677 #if defined(OS_MACOSX) |
668 if (options.synchronize) { | 678 if (options.synchronize) { |
(...skipping 22 matching lines...) Expand all Loading... | |
691 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { | 701 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { |
692 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); | 702 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); |
693 } | 703 } |
694 } else { | 704 } else { |
695 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); | 705 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); |
696 } | 706 } |
697 } | 707 } |
698 #endif // defined(OS_CHROMEOS) | 708 #endif // defined(OS_CHROMEOS) |
699 | 709 |
700 if (options.fds_to_remap) { | 710 if (options.fds_to_remap) { |
711 #ifdef USE_ALLOCATED_TYPE | |
712 SuspendAllocatedTypeIntercept(); | |
713 #endif | |
701 for (FileHandleMappingVector::const_iterator | 714 for (FileHandleMappingVector::const_iterator |
702 it = options.fds_to_remap->begin(); | 715 it = options.fds_to_remap->begin(); |
703 it != options.fds_to_remap->end(); ++it) { | 716 it != options.fds_to_remap->end(); ++it) { |
704 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); | 717 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); |
705 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); | 718 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); |
706 } | 719 } |
720 #ifdef USE_ALLOCATED_TYPE | |
721 ResumeAllocatedTypeIntercept(); | |
722 #endif | |
707 } | 723 } |
708 | 724 |
709 #if defined(OS_MACOSX) | 725 #if defined(OS_MACOSX) |
710 if (options.synchronize) { | 726 if (options.synchronize) { |
727 #ifdef USE_ALLOCATED_TYPE | |
728 SuspendAllocatedTypeIntercept(); | |
729 #endif | |
711 // Remap the read side of the synchronization pipe back onto itself, | 730 // Remap the read side of the synchronization pipe back onto itself, |
712 // ensuring that it won't be closed by CloseSuperfluousFds. | 731 // ensuring that it won't be closed by CloseSuperfluousFds. |
713 int keep_fd = *synchronization_read_fd.get(); | 732 int keep_fd = *synchronization_read_fd.get(); |
714 fd_shuffle1.push_back(InjectionArc(keep_fd, keep_fd, false)); | 733 fd_shuffle1.push_back(InjectionArc(keep_fd, keep_fd, false)); |
715 fd_shuffle2.push_back(InjectionArc(keep_fd, keep_fd, false)); | 734 fd_shuffle2.push_back(InjectionArc(keep_fd, keep_fd, false)); |
735 #ifdef USE_ALLOCATED_TYPE | |
736 ResumeAllocatedTypeIntercept(); | |
737 #endif | |
716 } | 738 } |
717 #endif // defined(OS_MACOSX) | 739 #endif // defined(OS_MACOSX) |
718 | 740 |
719 if (options.environ) | 741 if (options.environ) |
720 SetEnvironment(new_environ.get()); | 742 SetEnvironment(new_environ.get()); |
721 | 743 |
744 #ifdef USE_ALLOCATED_TYPE | |
745 SuspendAllocatedTypeIntercept(); | |
746 #endif | |
722 // fd_shuffle1 is mutated by this call because it cannot malloc. | 747 // fd_shuffle1 is mutated by this call because it cannot malloc. |
723 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 748 if (!ShuffleFileDescriptors(&fd_shuffle1)) { |
749 #ifdef USE_ALLOCATED_TYPE | |
750 ResumeAllocatedTypeIntercept(); | |
751 #endif | |
724 _exit(127); | 752 _exit(127); |
753 } | |
725 | 754 |
726 CloseSuperfluousFds(fd_shuffle2); | 755 CloseSuperfluousFds(fd_shuffle2); |
756 #ifdef USE_ALLOCATED_TYPE | |
757 ResumeAllocatedTypeIntercept(); | |
758 #endif | |
727 | 759 |
728 #if defined(OS_MACOSX) | 760 #if defined(OS_MACOSX) |
729 if (options.synchronize) { | 761 if (options.synchronize) { |
730 // Do a blocking read to wait until the parent says it's OK to proceed. | 762 // 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. | 763 // The byte that's read here is written by LaunchSynchronize. |
732 char read_char; | 764 char read_char; |
733 int read_result = | 765 int read_result = |
734 HANDLE_EINTR(read(*synchronization_read_fd.get(), &read_char, 1)); | 766 HANDLE_EINTR(read(*synchronization_read_fd.get(), &read_char, 1)); |
735 if (read_result != 1) { | 767 if (read_result != 1) { |
736 RAW_LOG(ERROR, "LaunchProcess: synchronization read: error"); | 768 RAW_LOG(ERROR, "LaunchProcess: synchronization read: error"); |
737 _exit(127); | 769 _exit(127); |
738 } | 770 } |
739 | 771 |
740 // The pipe is no longer useful. Don't let it live on in the new process | 772 // The pipe is no longer useful. Don't let it live on in the new process |
741 // after exec. | 773 // after exec. |
742 synchronization_read_fd.reset(); // closes synchronization_pipe_fds[0] | 774 synchronization_read_fd.reset(); // closes synchronization_pipe_fds[0] |
743 } | 775 } |
744 #endif // defined(OS_MACOSX) | 776 #endif // defined(OS_MACOSX) |
745 | 777 |
778 #ifdef USE_ALLOCATED_TYPE | |
779 SuspendAllocatedTypeIntercept(); | |
780 #endif | |
746 for (size_t i = 0; i < argv.size(); i++) | 781 for (size_t i = 0; i < argv.size(); i++) |
747 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 782 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
748 argv_cstr[argv.size()] = NULL; | 783 argv_cstr[argv.size()] = NULL; |
784 #ifdef USE_ALLOCATED_TYPE | |
785 ResumeAllocatedTypeIntercept(); | |
Alexander Potapenko
2012/08/02 14:57:12
There's no point in resuming the interception if t
Dai Mikurube (NOT FULLTIME)
2012/08/03 10:01:50
Ah, right. For now, I kept it as is, but I added
jar (doing other things)
2012/08/04 01:13:47
It strikes me that when you fork, you don't want t
Dai Mikurube (NOT FULLTIME)
2012/08/07 10:39:18
Ahhh, maybe, you are right. guessing we can suspe
| |
786 #endif | |
749 execvp(argv_cstr[0], argv_cstr.get()); | 787 execvp(argv_cstr[0], argv_cstr.get()); |
750 | 788 |
751 RAW_LOG(ERROR, "LaunchProcess: failed to execvp:"); | 789 RAW_LOG(ERROR, "LaunchProcess: failed to execvp:"); |
752 RAW_LOG(ERROR, argv_cstr[0]); | 790 RAW_LOG(ERROR, argv_cstr[0]); |
753 _exit(127); | 791 _exit(127); |
754 } else { | 792 } else { |
755 // Parent process | 793 // Parent process |
756 if (options.wait) { | 794 if (options.wait) { |
757 // While this isn't strictly disk IO, waiting for another process to | 795 // While this isn't strictly disk IO, waiting for another process to |
758 // finish is the sort of thing ThreadRestrictions is trying to prevent. | 796 // 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 | 1139 |
1102 // Obscure fork() rule: in the child, if you don't end up doing exec*(), | 1140 // 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 | 1141 // you call _exit() instead of exit(). This is because _exit() does not |
1104 // call any previously-registered (in the parent) exit handlers, which | 1142 // call any previously-registered (in the parent) exit handlers, which |
1105 // might do things like block waiting for threads that don't even exist | 1143 // might do things like block waiting for threads that don't even exist |
1106 // in the child. | 1144 // in the child. |
1107 int dev_null = open("/dev/null", O_WRONLY); | 1145 int dev_null = open("/dev/null", O_WRONLY); |
1108 if (dev_null < 0) | 1146 if (dev_null < 0) |
1109 _exit(127); | 1147 _exit(127); |
1110 | 1148 |
1149 #ifdef USE_ALLOCATED_TYPE | |
1150 SuspendAllocatedTypeIntercept(); | |
1151 #endif | |
1111 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); | 1152 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); |
1112 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); | 1153 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); |
1113 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); | 1154 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); |
1114 // Adding another element here? Remeber to increase the argument to | 1155 // Adding another element here? Remeber to increase the argument to |
1115 // reserve(), above. | 1156 // reserve(), above. |
1116 | 1157 |
1117 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(), | 1158 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(), |
1118 std::back_inserter(fd_shuffle2)); | 1159 std::back_inserter(fd_shuffle2)); |
1119 | 1160 |
1120 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 1161 if (!ShuffleFileDescriptors(&fd_shuffle1)) { |
1162 #ifdef USE_ALLOCATED_TYPE | |
1163 ResumeAllocatedTypeIntercept(); | |
1164 #endif | |
1121 _exit(127); | 1165 _exit(127); |
1166 } | |
1122 | 1167 |
1123 CloseSuperfluousFds(fd_shuffle2); | 1168 CloseSuperfluousFds(fd_shuffle2); |
1124 | 1169 |
1125 for (size_t i = 0; i < argv.size(); i++) | 1170 for (size_t i = 0; i < argv.size(); i++) |
1126 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 1171 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
1127 argv_cstr[argv.size()] = NULL; | 1172 argv_cstr[argv.size()] = NULL; |
1173 #ifdef USE_ALLOCATED_TYPE | |
1174 ResumeAllocatedTypeIntercept(); | |
1175 #endif | |
1128 if (do_search_path) | 1176 if (do_search_path) |
1129 execvp(argv_cstr[0], argv_cstr.get()); | 1177 execvp(argv_cstr[0], argv_cstr.get()); |
1130 else | 1178 else |
1131 execve(argv_cstr[0], argv_cstr.get(), envp); | 1179 execve(argv_cstr[0], argv_cstr.get(), envp); |
1132 _exit(127); | 1180 _exit(127); |
1133 } | 1181 } |
1134 default: // parent | 1182 default: // parent |
1135 { | 1183 { |
1136 // Close our writing end of pipe now. Otherwise later read would not | 1184 // 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 | 1185 // 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)) | 1376 if (IsChildDead(process)) |
1329 return; | 1377 return; |
1330 | 1378 |
1331 BackgroundReaper* reaper = new BackgroundReaper(process, 0); | 1379 BackgroundReaper* reaper = new BackgroundReaper(process, 0); |
1332 PlatformThread::CreateNonJoinable(0, reaper); | 1380 PlatformThread::CreateNonJoinable(0, reaper); |
1333 } | 1381 } |
1334 | 1382 |
1335 #endif // !defined(OS_MACOSX) | 1383 #endif // !defined(OS_MACOSX) |
1336 | 1384 |
1337 } // namespace base | 1385 } // namespace base |
OLD | NEW |