Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / compiler-rt / test / tsan / pthread_atfork_deadlock3.c
blob793eaf6ac867472c26302b3495d7d85b1d8dd29b
1 // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t > %t.out
2 // RUN: FileCheck %s --check-prefixes=CHECK,PARENT --input-file %t.out
3 // RUN: FileCheck %s --check-prefixes=CHECK,CHILD --input-file %t.out
4 // Regression test for
5 // https://groups.google.com/g/thread-sanitizer/c/TQrr4-9PRYo/m/HFR4FMi6AQAJ
6 #include "test.h"
7 #include <errno.h>
8 #include <signal.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/wait.h>
13 long glob = 0;
15 void *worker(void *main) {
16 glob++;
17 // synchronize with main
18 barrier_wait(&barrier);
19 // synchronize with atfork
20 barrier_wait(&barrier);
21 pthread_kill((pthread_t)main, SIGPROF);
22 barrier_wait(&barrier);
23 // synchronize with afterfork
24 barrier_wait(&barrier);
25 pthread_kill((pthread_t)main, SIGPROF);
26 barrier_wait(&barrier);
27 return NULL;
30 void atfork() {
31 barrier_wait(&barrier);
32 barrier_wait(&barrier);
33 write(2, "in atfork\n", strlen("in atfork\n"));
34 static volatile long a;
35 __atomic_fetch_add(&a, 1, __ATOMIC_RELEASE);
38 void afterfork() {
39 barrier_wait(&barrier);
40 barrier_wait(&barrier);
41 write(2, "in afterfork\n", strlen("in afterfork\n"));
42 static volatile long a;
43 __atomic_fetch_add(&a, 1, __ATOMIC_RELEASE);
46 void afterfork_child() {
47 write(2, "in afterfork_child\n", strlen("in afterfork_child\n"));
48 glob++;
51 void handler(int sig) {
52 write(2, "in handler\n", strlen("in handler\n"));
53 glob++;
56 int main() {
57 barrier_init(&barrier, 2);
58 struct sigaction act = {};
59 act.sa_handler = &handler;
60 if (sigaction(SIGPROF, &act, 0)) {
61 perror("sigaction");
62 exit(1);
64 pthread_atfork(atfork, afterfork, afterfork_child);
65 pthread_t t;
66 pthread_create(&t, NULL, worker, (void *)pthread_self());
67 barrier_wait(&barrier);
68 pid_t pid = fork();
69 if (pid < 0) {
70 fprintf(stderr, "fork failed: %d\n", errno);
71 return 1;
73 if (pid == 0) {
74 fprintf(stderr, "CHILD\n");
75 return 0;
77 if (pid != waitpid(pid, NULL, 0)) {
78 fprintf(stderr, "waitpid failed: %d\n", errno);
79 return 1;
81 pthread_join(t, NULL);
82 fprintf(stderr, "PARENT\n");
83 return 0;
86 // CHECK: in atfork
87 // CHECK: in handler
88 // CHECK: ThreadSanitizer: data race
89 // CHECK: Write of size 8
90 // CHECK: #0 handler
91 // CHECK: Previous write of size 8
92 // CHECK: #0 worker
93 // PARENT: afterfork
94 // PARENT: in handler
95 // CHILD: afterfork_child
96 // CHILD: CHILD
97 // CHECK: PARENT