1 // RUN: %clangxx_tsan %s -o %t && %run %t 2>&1 | FileCheck %s
2 
3 #include <pthread.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <signal.h>
7 #include <sys/types.h>
8 #include <sys/time.h>
9 #include <unistd.h>
10 #include <errno.h>
11 
12 volatile bool signal_delivered;
13 
handler(int sig)14 static void handler(int sig) {
15   if (sig == SIGALRM)
16     signal_delivered = true;
17 }
18 
thr(void * p)19 static void* thr(void *p) {
20   sigset_t sigset;
21   sigemptyset(&sigset);
22   sigaddset(&sigset, SIGALRM);
23   int ret = pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
24   if (ret) abort();
25 
26   struct sigaction act = {};
27   act.sa_handler = &handler;
28   if (sigaction(SIGALRM, &act, 0)) {
29     perror("sigaction");
30     exit(1);
31   }
32 
33   itimerval t;
34   t.it_value.tv_sec = 0;
35   t.it_value.tv_usec = 10000;
36   t.it_interval = t.it_value;
37   if (setitimer(ITIMER_REAL, &t, 0)) {
38     perror("setitimer");
39     exit(1);
40   }
41 
42   while (!signal_delivered) {
43     usleep(1000);
44   }
45 
46   t.it_value.tv_usec = 0;
47   if (setitimer(ITIMER_REAL, &t, 0)) {
48     perror("setitimer");
49     exit(1);
50   }
51 
52   fprintf(stderr, "SIGNAL DELIVERED\n");
53 
54   return 0;
55 }
56 
main()57 int main() {
58   sigset_t sigset;
59   sigemptyset(&sigset);
60   sigaddset(&sigset, SIGALRM);
61   int ret = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
62   if (ret) abort();
63 
64   pthread_t th;
65   pthread_create(&th, 0, thr, 0);
66   pthread_join(th, 0);
67 
68   fprintf(stderr, "DONE\n");
69   return 0;
70 }
71 
72 // CHECK-NOT: WARNING: ThreadSanitizer:
73 // CHECK: SIGNAL DELIVERED
74 // CHECK: DONE
75 // CHECK-NOT: WARNING: ThreadSanitizer:
76