xref: /llvm-project/compiler-rt/test/tsan/fork_multithreaded.cpp (revision d95baa98f34f01bea4fdab92c545bd3b24b697ee)
1 // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 66 2>&1 | FileCheck %s -check-prefix=CHECK-DIE
2 // RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=die_after_fork=0 %run %t 2>&1 | FileCheck %s -check-prefix=CHECK-NODIE
3 #include "test.h"
4 #include <errno.h>
5 #include <sys/types.h>
6 #include <sys/wait.h>
7 
sleeper(void * p)8 static void *sleeper(void *p) {
9   barrier_wait(&barrier);
10   return 0;
11 }
12 
nop(void * p)13 static void *nop(void *p) {
14   return 0;
15 }
16 
main(int argc,const char ** argv)17 int main(int argc, const char **argv) {
18   barrier_init(&barrier, 3);
19   const int kSleeperThreads = 2;
20   barrier_init(&barrier, kSleeperThreads + 1);
21   pthread_t th0[kSleeperThreads];
22   for (int i = 0; i < kSleeperThreads; i++)
23     pthread_create(&th0[i], 0, sleeper, 0);
24   const int kNopThreads = 5;
25   pthread_t th1[kNopThreads];
26   for (int i = 0; i < kNopThreads; i++)
27     pthread_create(&th1[i], 0, nop, 0);
28   for (int i = 0; i < kNopThreads; i++)
29     pthread_join(th1[i], 0);
30   int pid = fork();
31   if (pid < 0) {
32     fprintf(stderr, "failed to fork (%d)\n", errno);
33     exit(1);
34   }
35   if (pid == 0) {
36     // child
37     const int kChildThreads = 4;
38     pthread_t th2[kChildThreads];
39     for (int i = 0; i < kChildThreads; i++)
40       pthread_create(&th2[i], 0, nop, 0);
41     for (int i = 0; i < kChildThreads; i++)
42       pthread_join(th2[i], 0);
43     exit(0);
44     return 0;
45   }
46   // parent
47   int expect = argc > 1 ? atoi(argv[1]) : 0;
48   int status = 0;
49   while (waitpid(pid, &status, 0) != pid) {
50   }
51   if (!WIFEXITED(status) || WEXITSTATUS(status) != expect) {
52     fprintf(stderr, "subprocess exited with %d, expected %d\n", status, expect);
53     exit(1);
54   }
55   barrier_wait(&barrier);
56   for (int i = 0; i < kSleeperThreads; i++)
57     pthread_join(th0[i], 0);
58   fprintf(stderr, "OK\n");
59   return 0;
60 }
61 
62 // CHECK-DIE: ThreadSanitizer: starting new threads after multi-threaded fork is not supported
63 
64 // CHECK-NODIE-NOT: ThreadSanitizer:
65 // CHECK-NODIE: OK
66 // CHECK-NODIE-NOT: ThreadSanitizer:
67