summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2014-05-13 16:17:54 +0000
committerAlexander Potapenko <glider@google.com>2014-05-13 16:17:54 +0000
commit8563d6ef39045d86b2791a7fae75fe803eff66b4 (patch)
tree451858f9902a212745e1f7e5a8b3f224ebce0baf
parentb58e7f412543c2641e2bc8d087fe6836f426cb92 (diff)
[libsanitizer] Use internal_fork() to spawn the symbolizer process.
This should fix https://code.google.com/p/thread-sanitizer/issues/detail?id=61 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@208707 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/sanitizer_common/sanitizer_libc.h2
-rw-r--r--lib/sanitizer_common/sanitizer_linux.cc4
-rw-r--r--lib/sanitizer_common/sanitizer_mac.cc5
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc3
-rw-r--r--test/tsan/pthread_atfork_deadlock.c31
5 files changed, 44 insertions, 1 deletions
diff --git a/lib/sanitizer_common/sanitizer_libc.h b/lib/sanitizer_common/sanitizer_libc.h
index 0768ae16e..a9d308e38 100644
--- a/lib/sanitizer_common/sanitizer_libc.h
+++ b/lib/sanitizer_common/sanitizer_libc.h
@@ -91,6 +91,8 @@ uptr internal_waitpid(int pid, int *status, int options);
uptr internal_getpid();
uptr internal_getppid();
+uptr internal_fork();
+
// Threading
uptr internal_sched_yield();
diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc
index f0daa89f0..c14232631 100644
--- a/lib/sanitizer_common/sanitizer_linux.cc
+++ b/lib/sanitizer_common/sanitizer_linux.cc
@@ -501,6 +501,10 @@ uptr internal_sigaltstack(const struct sigaltstack *ss,
return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
}
+uptr internal_fork() {
+ return internal_syscall(SYSCALL(fork));
+}
+
#if SANITIZER_LINUX
// Doesn't set sa_restorer, use with caution (see below).
int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc
index 747513de5..7a4a0d586 100644
--- a/lib/sanitizer_common/sanitizer_mac.cc
+++ b/lib/sanitizer_common/sanitizer_mac.cc
@@ -126,6 +126,11 @@ int internal_sigaction(int signum, const void *act, void *oldact) {
(struct sigaction *)act, (struct sigaction *)oldact);
}
+int internal_fork() {
+ // TODO(glider): this may call user's pthread_atfork() handlers which is bad.
+ return fork();
+}
+
// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
struct stat st;
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
index a87bfbf1a..ca47e3c83 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
@@ -234,7 +234,8 @@ class SymbolizerProcess : public ExternalSymbolizerInterface {
CHECK(infd);
CHECK(outfd);
- int pid = fork();
+ // Real fork() may call user callbacks registered with pthread_atfork().
+ int pid = internal_fork();
if (pid == -1) {
// Fork() failed.
internal_close(infd[0]);
diff --git a/test/tsan/pthread_atfork_deadlock.c b/test/tsan/pthread_atfork_deadlock.c
new file mode 100644
index 000000000..27dff46b9
--- /dev/null
+++ b/test/tsan/pthread_atfork_deadlock.c
@@ -0,0 +1,31 @@
+// RUN: %clang_tsan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// Regression test for
+// https://code.google.com/p/thread-sanitizer/issues/detail?id=61
+// When the data race was reported, pthread_atfork() handler used to be
+// executed which caused another race report in the same thread, which resulted
+// in a deadlock.
+#include <pthread.h>
+#include <stdio.h>
+
+int glob = 0;
+
+void *worker(void *unused) {
+ glob++;
+ return NULL;
+}
+
+void atfork() {
+ fprintf(stderr, "ATFORK\n");
+ glob++;
+}
+
+int main() {
+ pthread_atfork(atfork, NULL, NULL);
+ pthread_t t;
+ pthread_create(&t, NULL, worker, NULL);
+ glob++;
+ pthread_join(t, NULL);
+ // CHECK: ThreadSanitizer: data race
+ // CHECK-NOT: ATFORK
+ return 0;
+}