1 | // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s |
2 | |
3 | // Test that a signal is not delivered when it is blocked. |
4 | |
5 | #include "test.h" |
6 | #include <semaphore.h> |
7 | #include <signal.h> |
8 | #include <errno.h> |
9 | |
10 | int stop; |
11 | sig_atomic_t signal_blocked; |
12 | |
13 | void handler(int signum) { |
14 | if (signal_blocked) { |
15 | fprintf(stderr, format: "signal arrived when blocked\n" ); |
16 | exit(status: 1); |
17 | } |
18 | } |
19 | |
20 | void *thread(void *arg) { |
21 | sigset_t myset; |
22 | sigemptyset(set: &myset); |
23 | sigaddset(set: &myset, SIGUSR1); |
24 | while (!__atomic_load_n(&stop, __ATOMIC_RELAXED)) { |
25 | usleep(useconds: 1); |
26 | if (pthread_sigmask(SIG_BLOCK, newmask: &myset, oldmask: 0)) { |
27 | fprintf(stderr, format: "pthread_sigmask failed %d\n" , errno); |
28 | exit(status: 1); |
29 | } |
30 | signal_blocked = 1; |
31 | usleep(useconds: 1); |
32 | signal_blocked = 0; |
33 | if (pthread_sigmask(SIG_UNBLOCK, newmask: &myset, oldmask: 0)) { |
34 | fprintf(stderr, format: "pthread_sigmask failed %d\n" , errno); |
35 | exit(status: 1); |
36 | } |
37 | } |
38 | return 0; |
39 | } |
40 | |
41 | int main(int argc, char** argv) { |
42 | struct sigaction act = {}; |
43 | act.sa_handler = &handler; |
44 | if (sigaction(SIGUSR1, act: &act, oact: 0)) { |
45 | fprintf(stderr, format: "sigaction failed %d\n" , errno); |
46 | return 1; |
47 | } |
48 | pthread_t th; |
49 | pthread_create(newthread: &th, attr: 0, start_routine: thread, arg: 0); |
50 | for (int i = 0; i < 100000; i++) |
51 | pthread_kill(threadid: th, SIGUSR1); |
52 | __atomic_store_n(&stop, 1, __ATOMIC_RELAXED); |
53 | pthread_join(th: th, thread_return: 0); |
54 | fprintf(stderr, format: "DONE\n" ); |
55 | return 0; |
56 | } |
57 | |
58 | // CHECK-NOT: ThreadSanitizer CHECK |
59 | // CHECK-NOT: WARNING: ThreadSanitizer: |
60 | // CHECK: DONE |
61 | |