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
11int glob = 0;
12
13void *worker(void *unused) {
14 glob++;
15 barrier_wait(&barrier);
16 return NULL;
17}
18
19void atfork() {
20 glob++;
21}
22
23int 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