diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2013-07-16 11:28:04 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2013-07-16 11:28:04 +0000 |
commit | fbeab51e1cddbeb73ad0d86d1f650081178c1dd8 (patch) | |
tree | 5e90df655a9e7c90f7e945c286d0097c7c0575ae | |
parent | bb7f2d880c843dd5ee1c5e53d2517f7ca9058e66 (diff) | |
download | compiler-rt-fbeab51e1cddbeb73ad0d86d1f650081178c1dd8.tar.gz compiler-rt-fbeab51e1cddbeb73ad0d86d1f650081178c1dd8.tar.bz2 compiler-rt-fbeab51e1cddbeb73ad0d86d1f650081178c1dd8.tar.xz |
tsan: support sigsuspend() call
Intercepting it makes it process pending signal before return.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@186400 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/tsan/lit_tests/sigsuspend.cc | 38 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors.cc | 6 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_stat.cc | 1 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_stat.h | 1 |
4 files changed, 46 insertions, 0 deletions
diff --git a/lib/tsan/lit_tests/sigsuspend.cc b/lib/tsan/lit_tests/sigsuspend.cc new file mode 100644 index 00000000..4da20a6f --- /dev/null +++ b/lib/tsan/lit_tests/sigsuspend.cc @@ -0,0 +1,38 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s +#include <assert.h> +#include <stdlib.h> +#include <signal.h> +#include <unistd.h> +#include <stdio.h> + +static bool signal_handler_ran = false; + +void do_nothing_signal_handler(int signum) { + write(1, "HANDLER\n", 8); + signal_handler_ran = true; +} + +int main() { + const int kSignalToTest = SIGSYS; + assert(SIG_ERR != signal(kSignalToTest, do_nothing_signal_handler)); + sigset_t empty_set; + assert(0 == sigemptyset(&empty_set)); + sigset_t one_signal = empty_set; + assert(0 == sigaddset(&one_signal, kSignalToTest)); + sigset_t old_set; + assert(0 == sigprocmask(SIG_BLOCK, &one_signal, &old_set)); + raise(kSignalToTest); + assert(!signal_handler_ran); + sigset_t all_but_one; + assert(0 == sigfillset(&all_but_one)); + assert(0 == sigdelset(&all_but_one, kSignalToTest)); + sigsuspend(&all_but_one); + assert(signal_handler_ran); + + // Restore the original set. + assert(0 == sigprocmask(SIG_SETMASK, &old_set, NULL)); + printf("DONE"); +} + +// CHECK: HANDLER +// CHECK: DONE diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 35a582cf..92d8ae19 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -1707,6 +1707,11 @@ TSAN_INTERCEPTOR(sighandler_t, signal, int sig, sighandler_t h) { return old.sa_handler; } +TSAN_INTERCEPTOR(int, sigsuspend, const sigset_t *mask) { + SCOPED_TSAN_INTERCEPTOR(sigsuspend, mask); + return REAL(sigsuspend)(mask); +} + TSAN_INTERCEPTOR(int, raise, int sig) { SCOPED_TSAN_INTERCEPTOR(raise, sig); SignalContext *sctx = SigCtx(thr); @@ -2071,6 +2076,7 @@ void InitializeInterceptors() { TSAN_INTERCEPT(sigaction); TSAN_INTERCEPT(signal); + TSAN_INTERCEPT(sigsuspend); TSAN_INTERCEPT(raise); TSAN_INTERCEPT(kill); TSAN_INTERCEPT(pthread_kill); diff --git a/lib/tsan/rtl/tsan_stat.cc b/lib/tsan/rtl/tsan_stat.cc index 3f153b6e..5e8cc18e 100644 --- a/lib/tsan/rtl/tsan_stat.cc +++ b/lib/tsan/rtl/tsan_stat.cc @@ -257,6 +257,7 @@ void StatOutput(u64 *stat) { name[StatInt_poll] = " poll "; name[StatInt_sigaction] = " sigaction "; name[StatInt_signal] = " signal "; + name[StatInt_sigsuspend] = " sigsuspend "; name[StatInt_raise] = " raise "; name[StatInt_kill] = " kill "; name[StatInt_pthread_kill] = " pthread_kill "; diff --git a/lib/tsan/rtl/tsan_stat.h b/lib/tsan/rtl/tsan_stat.h index 36b298e4..61317215 100644 --- a/lib/tsan/rtl/tsan_stat.h +++ b/lib/tsan/rtl/tsan_stat.h @@ -252,6 +252,7 @@ enum StatType { StatInt_poll, StatInt_sigaction, StatInt_signal, + StatInt_sigsuspend, StatInt_raise, StatInt_kill, StatInt_pthread_kill, |