xref: /llvm-project/compiler-rt/test/tsan/signal_in_read.c (revision cf1319f9c6561afea381bbfc1a18f5c1fb7b46b0)
1 // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
2 
3 #include "test.h"
4 
5 #include <assert.h>
6 #include <errno.h>
7 #include <pthread.h>
8 #include <signal.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 
13 static int SignalPipeFd[] = {-1, -1};
14 static int BlockingPipeFd[] = {-1, -1};
15 
Handler(int _)16 static void Handler(int _) { assert(write(SignalPipeFd[1], ".", 1) == 1); }
17 
ThreadFunc(void * _)18 static void *ThreadFunc(void *_) {
19   char C;
20   assert(read(BlockingPipeFd[0], &C, sizeof(C)) == 1);
21   assert(C == '.');
22   return 0;
23 }
24 
main()25 int main() {
26   alarm(60); // Kill the test if it hangs.
27 
28   assert(pipe(SignalPipeFd) == 0);
29   assert(pipe(BlockingPipeFd) == 0);
30 
31   struct sigaction act;
32   sigemptyset(&act.sa_mask);
33   act.sa_flags = SA_RESTART;
34   act.sa_handler = Handler;
35   assert(sigaction(SIGUSR1, &act, 0) == 0);
36 
37   pthread_t Thr;
38   assert(pthread_create(&Thr, 0, ThreadFunc, 0) == 0);
39 
40   // Give the thread enough time to block in the read call.
41   usleep(1000000);
42 
43   // Signal the thread, this should run the signal handler and unblock the read
44   // below.
45   pthread_kill(Thr, SIGUSR1);
46   char C;
47   assert(read(SignalPipeFd[0], &C, 1) == 1);
48 
49   // Unblock the thread and join it.
50   assert(write(BlockingPipeFd[1], &C, 1) == 1);
51   void *_ = 0;
52   assert(pthread_join(Thr, &_) == 0);
53 
54   fprintf(stderr, "PASS\n");
55   return 0;
56 }
57 
58 // CHECK-NOT: WARNING: ThreadSanitizer:
59 // CHECK: PASS
60