diff options
author | Kuba Brecka <kuba.brecka@gmail.com> | 2015-11-20 14:28:33 +0000 |
---|---|---|
committer | Kuba Brecka <kuba.brecka@gmail.com> | 2015-11-20 14:28:33 +0000 |
commit | 8dbf679e72e43d7c6b565417a8b0716943cb191b (patch) | |
tree | 04eff5d7bc067306898501ab9dca330a7e10fcd9 /lib/sanitizer_common | |
parent | bc3baa86f7b20c2d5b00294a8cd9f40be109d593 (diff) |
[sanitizer] Implement internal_fork and internal_forkpty for OS X
On Linux, we have internal_fork that forks without invoking user's pthread_atfork handlers, which is important for spawning external symbolizers. Let's implement this for OS X as well (using __fork). This patch also adds internal_forkpty which re-implements forkpty and uses __fork in it as well.
Differential Revision: http://reviews.llvm.org/D14869
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@253666 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common')
-rw-r--r-- | lib/sanitizer_common/sanitizer_mac.cc | 26 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_posix.h | 1 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc | 2 |
3 files changed, 26 insertions, 3 deletions
diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 03e97c84e..11d27e864 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -52,6 +52,7 @@ extern char **environ; #include <sys/sysctl.h> #include <sys/types.h> #include <unistd.h> +#include <util.h> namespace __sanitizer { @@ -147,9 +148,30 @@ uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, return sigprocmask(how, set, oldset); } +// Doesn't call pthread_atfork() handlers. +extern "C" pid_t __fork(void); + int internal_fork() { - // TODO(glider): this may call user's pthread_atfork() handlers which is bad. - return fork(); + return __fork(); +} + +int internal_forkpty(int *amaster) { + int master, slave; + if (openpty(&master, &slave, nullptr, nullptr, nullptr) == -1) return -1; + int pid = __fork(); + if (pid == -1) { + close(master); + close(slave); + return -1; + } + if (pid == 0) { + close(master); + CHECK_EQ(login_tty(slave), 0); + } else { + *amaster = master; + close(slave); + } + return pid; } uptr internal_rename(const char *oldpath, const char *newpath) { diff --git a/lib/sanitizer_common/sanitizer_posix.h b/lib/sanitizer_common/sanitizer_posix.h index 19fa505c5..c0426a0b2 100644 --- a/lib/sanitizer_common/sanitizer_posix.h +++ b/lib/sanitizer_common/sanitizer_posix.h @@ -54,6 +54,7 @@ uptr internal_ptrace(int request, int pid, void *addr, void *data); uptr internal_waitpid(int pid, int *status, int options); int internal_fork(); +int internal_forkpty(int *amaster); // These functions call appropriate pthread_ functions directly, bypassing // the interceptor. They are weak and may not be present in some tools. diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc index a19b0a678..3cf672f84 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -75,7 +75,7 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() { #if SANITIZER_MAC fd_t fd = kInvalidFd; // Use forkpty to disable buffering in the new terminal. - pid = forkpty(&fd, 0, 0, 0); + pid = internal_forkpty(&fd); if (pid == -1) { // forkpty() failed. Report("WARNING: failed to fork external symbolizer (errno: %d)\n", |