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