Chromium Code Reviews| 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 |