[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

llvm-svn: 253666
This commit is contained in:
Kuba Brecka 2015-11-20 14:28:33 +00:00
parent e08533577f
commit 1f73ba6053
3 changed files with 26 additions and 3 deletions

View File

@ -52,6 +52,7 @@ extern char **environ;
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <util.h>
namespace __sanitizer { namespace __sanitizer {
@ -147,9 +148,30 @@ uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
return sigprocmask(how, set, oldset); return sigprocmask(how, set, oldset);
} }
// Doesn't call pthread_atfork() handlers.
extern "C" pid_t __fork(void);
int internal_fork() { 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) { uptr internal_rename(const char *oldpath, const char *newpath) {

View File

@ -54,6 +54,7 @@ uptr internal_ptrace(int request, int pid, void *addr, void *data);
uptr internal_waitpid(int pid, int *status, int options); uptr internal_waitpid(int pid, int *status, int options);
int internal_fork(); int internal_fork();
int internal_forkpty(int *amaster);
// These functions call appropriate pthread_ functions directly, bypassing // These functions call appropriate pthread_ functions directly, bypassing
// the interceptor. They are weak and may not be present in some tools. // the interceptor. They are weak and may not be present in some tools.

View File

@ -75,7 +75,7 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
#if SANITIZER_MAC #if SANITIZER_MAC
fd_t fd = kInvalidFd; fd_t fd = kInvalidFd;
// Use forkpty to disable buffering in the new terminal. // Use forkpty to disable buffering in the new terminal.
pid = forkpty(&fd, 0, 0, 0); pid = internal_forkpty(&fd);
if (pid == -1) { if (pid == -1) {
// forkpty() failed. // forkpty() failed.
Report("WARNING: failed to fork external symbolizer (errno: %d)\n", Report("WARNING: failed to fork external symbolizer (errno: %d)\n",