diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2016-07-27 14:34:21 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2016-07-27 14:34:21 +0000 |
commit | e6d32453fdf31ea68cc57cf9726433309620d8c1 (patch) | |
tree | 9b82f644fbd70c9efc11f4e099ef16fb928e5e82 /test | |
parent | 8f6f38274ef55051f5923e4d532d0dc9b9836ee3 (diff) |
tsan: don't deliver signals when they are blocked
When we delay signals we can deliver them when the signal
is blocked. This can be surprising to the program.
Intercept signal blocking functions merely to process
pending signals. As the result, at worst we will delay
a signal till return from the signal blocking function.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@276876 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r-- | test/tsan/signal_block.cc | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/test/tsan/signal_block.cc b/test/tsan/signal_block.cc new file mode 100644 index 000000000..dfd4259c4 --- /dev/null +++ b/test/tsan/signal_block.cc @@ -0,0 +1,60 @@ +// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s + +// Test that a signal is not delivered when it is blocked. + +#include "test.h" +#include <semaphore.h> +#include <signal.h> +#include <errno.h> + +int stop; +sig_atomic_t signal_blocked; + +void handler(int signum) { + if (signal_blocked) { + fprintf(stderr, "signal arrived when blocked\n"); + exit(1); + } +} + +void *thread(void *arg) { + sigset_t myset; + sigemptyset(&myset); + sigaddset(&myset, SIGUSR1); + while (!__atomic_load_n(&stop, __ATOMIC_RELAXED)) { + usleep(1); + if (pthread_sigmask(SIG_BLOCK, &myset, 0)) { + fprintf(stderr, "pthread_sigmask failed %d\n", errno); + exit(1); + } + signal_blocked = 1; + usleep(1); + signal_blocked = 0; + if (pthread_sigmask(SIG_UNBLOCK, &myset, 0)) { + fprintf(stderr, "pthread_sigmask failed %d\n", errno); + exit(1); + } + } + return 0; +} + +int main(int argc, char** argv) { + struct sigaction act = {}; + act.sa_handler = &handler; + if (sigaction(SIGUSR1, &act, 0)) { + fprintf(stderr, "sigaction failed %d\n", errno); + return 1; + } + pthread_t th; + pthread_create(&th, 0, thread, 0); + for (int i = 0; i < 100000; i++) + pthread_kill(th, SIGUSR1); + __atomic_store_n(&stop, 1, __ATOMIC_RELAXED); + pthread_join(th, 0); + fprintf(stderr, "DONE\n"); + return 0; +} + +// CHECK-NOT: ThreadSanitizer CHECK +// CHECK-NOT: WARNING: ThreadSanitizer: +// CHECK: DONE |