1 // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
2 // Regression test for
3 // https://groups.google.com/d/msg/thread-sanitizer/e_zB9gYqFHM/DmAiTsrLAwAJ
4 // pthread_atfork() callback triggers a data race and we deadlocked
5 // on the report_mtx as we lock it around fork.
6 #include "test.h"
7 #include <sys/types.h>
8 #include <sys/wait.h>
9 #include <errno.h>
10 
11 int glob = 0;
12 
worker(void * unused)13 void *worker(void *unused) {
14   glob++;
15   barrier_wait(&barrier);
16   return NULL;
17 }
18 
atfork()19 void atfork() {
20   glob++;
21 }
22 
main()23 int main() {
24   barrier_init(&barrier, 2);
25   pthread_atfork(atfork, atfork, atfork);
26   pthread_t t;
27   pthread_create(&t, NULL, worker, NULL);
28   barrier_wait(&barrier);
29   pid_t pid = fork();
30   if (pid < 0) {
31     fprintf(stderr, "fork failed: %d\n", errno);
32     return 1;
33   }
34   if (pid == 0) {
35     fprintf(stderr, "CHILD\n");
36     return 0;
37   }
38   if (pid != waitpid(pid, NULL, 0)) {
39     fprintf(stderr, "waitpid failed: %d\n", errno);
40     return 1;
41   }
42   pthread_join(t, NULL);
43   fprintf(stderr, "PARENT\n");
44   return 0;
45 }
46 
47 // CHECK: ThreadSanitizer: data race
48 // CHECK:   Write of size 4
49 // CHECK:     #0 atfork
50 // CHECK:   Previous write of size 4
51 // CHECK:     #0 worker
52 // CHECK: CHILD
53 // CHECK: PARENT
54