From 1a0c76fa55e46c7caf0f9af53299524963e52382 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 16 Jul 2013 11:28:04 +0000 Subject: [PATCH] tsan: support sigsuspend() call Intercepting it makes it process pending signal before return. llvm-svn: 186400 --- compiler-rt/lib/tsan/lit_tests/sigsuspend.cc | 38 +++++++++++++++++++++++++++ compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 6 +++++ compiler-rt/lib/tsan/rtl/tsan_stat.cc | 1 + compiler-rt/lib/tsan/rtl/tsan_stat.h | 1 + 4 files changed, 46 insertions(+) create mode 100644 compiler-rt/lib/tsan/lit_tests/sigsuspend.cc diff --git a/compiler-rt/lib/tsan/lit_tests/sigsuspend.cc b/compiler-rt/lib/tsan/lit_tests/sigsuspend.cc new file mode 100644 index 0000000..4da20a6 --- /dev/null +++ b/compiler-rt/lib/tsan/lit_tests/sigsuspend.cc @@ -0,0 +1,38 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s +#include +#include +#include +#include +#include + +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/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index 35a582c..92d8ae1 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/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/compiler-rt/lib/tsan/rtl/tsan_stat.cc b/compiler-rt/lib/tsan/rtl/tsan_stat.cc index 3f153b6..5e8cc18 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.cc +++ b/compiler-rt/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/compiler-rt/lib/tsan/rtl/tsan_stat.h b/compiler-rt/lib/tsan/rtl/tsan_stat.h index 36b298e..6131721 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.h +++ b/compiler-rt/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, -- 2.7.4