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 "base/process/launch.h" | 5 #include "base/process/launch.h" |
| 6 | 6 |
| 7 #include <dirent.h> | 7 #include <dirent.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <signal.h> | 10 #include <signal.h> |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 // Set the process's "environment" (i.e. the thing that setenv/getenv | 70 // Set the process's "environment" (i.e. the thing that setenv/getenv |
| 71 // work with). | 71 // work with). |
| 72 void SetEnvironment(char** env) { | 72 void SetEnvironment(char** env) { |
| 73 #if defined(OS_MACOSX) | 73 #if defined(OS_MACOSX) |
| 74 *_NSGetEnviron() = env; | 74 *_NSGetEnviron() = env; |
| 75 #else | 75 #else |
| 76 environ = env; | 76 environ = env; |
| 77 #endif | 77 #endif |
| 78 } | 78 } |
| 79 | 79 |
| 80 // List of signals that we want to block while forking and then reset | |
| 81 // to SIG_DFL in the child process. | |
| 82 // The previous signal handlers are likely to be meaningless in the child's | |
| 83 // context so we reset them to the defaults for now. http://crbug.com/44953 | |
| 84 // These signal handlers are set up at least in browser_main_posix.cc: | |
| 85 // BrowserMainPartsPosix::PreEarlyInitialization and stack_trace_posix.cc: | |
| 86 // EnableInProcessStackDumping. | |
| 87 const int kSignalsToReset[] = { | |
|
jln (very slow on Chromium)
2013/07/31 23:54:55
This ignores the other implementation of ResetChil
mdempsky_google
2013/08/01 00:31:57
Uploaded a new patch that's slightly simpler and j
| |
| 88 SIGHUP, | |
| 89 SIGINT, | |
| 90 SIGILL, | |
| 91 SIGABRT, | |
| 92 SIGFPE, | |
| 93 SIGBUS, | |
| 94 SIGSEGV, | |
| 95 SIGSYS, | |
| 96 SIGTERM, | |
| 97 }; | |
| 98 | |
| 80 #if !defined(OS_LINUX) || \ | 99 #if !defined(OS_LINUX) || \ |
| 81 (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) | 100 (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) |
| 82 void ResetChildSignalHandlersToDefaults() { | 101 void ResetChildSignalHandlersToDefaults() { |
| 83 // The previous signal handlers are likely to be meaningless in the child's | 102 for (size_t i = 0; i < arraysize(kSignalsToReset); i++) { |
| 84 // context so we reset them to the defaults for now. http://crbug.com/44953 | 103 signal(kSignalsToReset[i], SIG_DFL); |
| 85 // These signal handlers are set up at least in browser_main_posix.cc: | 104 } |
| 86 // BrowserMainPartsPosix::PreEarlyInitialization and stack_trace_posix.cc: | |
| 87 // EnableInProcessStackDumping. | |
| 88 signal(SIGHUP, SIG_DFL); | |
| 89 signal(SIGINT, SIG_DFL); | |
| 90 signal(SIGILL, SIG_DFL); | |
| 91 signal(SIGABRT, SIG_DFL); | |
| 92 signal(SIGFPE, SIG_DFL); | |
| 93 signal(SIGBUS, SIG_DFL); | |
| 94 signal(SIGSEGV, SIG_DFL); | |
| 95 signal(SIGSYS, SIG_DFL); | |
| 96 signal(SIGTERM, SIG_DFL); | |
| 97 } | 105 } |
| 98 | 106 |
| 99 #else | 107 #else |
| 100 | 108 |
| 101 // TODO(jln): remove the Linux special case once kernels are fixed. | 109 // TODO(jln): remove the Linux special case once kernels are fixed. |
| 102 | 110 |
| 103 // Internally the kernel makes sigset_t an array of long large enough to have | 111 // Internally the kernel makes sigset_t an array of long large enough to have |
| 104 // one bit per signal. | 112 // one bit per signal. |
| 105 typedef uint64_t kernel_sigset_t; | 113 typedef uint64_t kernel_sigset_t; |
| 106 | 114 |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 InjectiveMultimap fd_shuffle1; | 395 InjectiveMultimap fd_shuffle1; |
| 388 InjectiveMultimap fd_shuffle2; | 396 InjectiveMultimap fd_shuffle2; |
| 389 fd_shuffle1.reserve(fd_shuffle_size); | 397 fd_shuffle1.reserve(fd_shuffle_size); |
| 390 fd_shuffle2.reserve(fd_shuffle_size); | 398 fd_shuffle2.reserve(fd_shuffle_size); |
| 391 | 399 |
| 392 scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]); | 400 scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]); |
| 393 scoped_ptr<char*[]> new_environ; | 401 scoped_ptr<char*[]> new_environ; |
| 394 if (options.environ) | 402 if (options.environ) |
| 395 new_environ.reset(AlterEnvironment(*options.environ, GetEnvironment())); | 403 new_environ.reset(AlterEnvironment(*options.environ, GetEnvironment())); |
| 396 | 404 |
| 405 sigset_t sigs_to_block; | |
| 406 sigemptyset(&sigs_to_block); | |
| 407 for (size_t i = 0; i < arraysize(kSignalsToReset); i++) { | |
| 408 sigaddset(&sigs_to_block, kSignalsToReset[i]); | |
| 409 } | |
| 410 | |
| 411 sigset_t old_sigset; | |
| 412 if (pthread_sigmask(SIG_BLOCK, &sigs_to_block, &old_sigset) != 0) { | |
| 413 DPLOG(ERROR) << "pthread_sigmask"; | |
| 414 return false; | |
| 415 } | |
| 416 | |
| 397 pid_t pid; | 417 pid_t pid; |
| 398 #if defined(OS_LINUX) | 418 #if defined(OS_LINUX) |
| 399 if (options.clone_flags) { | 419 if (options.clone_flags) { |
| 400 pid = syscall(__NR_clone, options.clone_flags, 0, 0, 0); | 420 pid = syscall(__NR_clone, options.clone_flags, 0, 0, 0); |
| 401 } else | 421 } else |
| 402 #endif | 422 #endif |
| 403 { | 423 { |
| 404 pid = fork(); | 424 pid = fork(); |
| 405 } | 425 } |
| 406 | 426 |
| 427 if (pid != 0) { | |
| 428 if (pthread_sigmask(SIG_SETMASK, &old_sigset, NULL) != 0) { | |
| 429 NOTREACHED(); | |
| 430 } | |
| 431 } | |
| 432 | |
| 407 if (pid < 0) { | 433 if (pid < 0) { |
| 408 DPLOG(ERROR) << "fork"; | 434 DPLOG(ERROR) << "fork"; |
| 409 return false; | 435 return false; |
| 410 } else if (pid == 0) { | 436 } else if (pid == 0) { |
| 411 // Child process | 437 // Child process |
| 412 | 438 |
| 413 // DANGER: fork() rule: in the child, if you don't end up doing exec*(), | 439 // DANGER: fork() rule: in the child, if you don't end up doing exec*(), |
| 414 // you call _exit() instead of exit(). This is because _exit() does not | 440 // you call _exit() instead of exit(). This is because _exit() does not |
| 415 // call any previously-registered (in the parent) exit handlers, which | 441 // call any previously-registered (in the parent) exit handlers, which |
| 416 // might do things like block waiting for threads that don't even exist | 442 // might do things like block waiting for threads that don't even exist |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 720 std::string* output, | 746 std::string* output, |
| 721 int* exit_code) { | 747 int* exit_code) { |
| 722 // Run |execve()| with the current environment and store "unlimited" data. | 748 // Run |execve()| with the current environment and store "unlimited" data. |
| 723 GetAppOutputInternalResult result = GetAppOutputInternal( | 749 GetAppOutputInternalResult result = GetAppOutputInternal( |
| 724 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, | 750 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, |
| 725 exit_code); | 751 exit_code); |
| 726 return result == EXECUTE_SUCCESS; | 752 return result == EXECUTE_SUCCESS; |
| 727 } | 753 } |
| 728 | 754 |
| 729 } // namespace base | 755 } // namespace base |
| OLD | NEW |