summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2016-07-27 14:34:21 +0000
committerDmitry Vyukov <dvyukov@google.com>2016-07-27 14:34:21 +0000
commite6d32453fdf31ea68cc57cf9726433309620d8c1 (patch)
tree9b82f644fbd70c9efc11f4e099ef16fb928e5e82 /test
parent8f6f38274ef55051f5923e4d532d0dc9b9836ee3 (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.cc60
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