98 lines · c
1// RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t > %t.out2// RUN: FileCheck %s --check-prefixes=CHECK,PARENT --input-file %t.out3// RUN: FileCheck %s --check-prefixes=CHECK,CHILD --input-file %t.out4// Regression test for5// https://groups.google.com/g/thread-sanitizer/c/TQrr4-9PRYo/m/HFR4FMi6AQAJ6#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>12 13long glob = 0;14 15void *worker(void *main) {16 glob++;17 // synchronize with main18 barrier_wait(&barrier);19 // synchronize with atfork20 barrier_wait(&barrier);21 pthread_kill((pthread_t)main, SIGPROF);22 barrier_wait(&barrier);23 // synchronize with afterfork24 barrier_wait(&barrier);25 pthread_kill((pthread_t)main, SIGPROF);26 barrier_wait(&barrier);27 return NULL;28}29 30void atfork() {31 write(2, "in atfork\n", strlen("in atfork\n"));32 barrier_wait(&barrier);33 barrier_wait(&barrier);34 static volatile long a;35 __atomic_fetch_add(&a, 1, __ATOMIC_RELEASE);36}37 38void afterfork() {39 write(2, "in afterfork\n", strlen("in afterfork\n"));40 barrier_wait(&barrier);41 barrier_wait(&barrier);42 static volatile long a;43 __atomic_fetch_add(&a, 1, __ATOMIC_RELEASE);44}45 46void afterfork_child() {47 write(2, "in afterfork_child\n", strlen("in afterfork_child\n"));48 glob++;49}50 51void handler(int sig) {52 write(2, "in handler\n", strlen("in handler\n"));53 glob++;54}55 56int 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);63 }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;72 }73 if (pid == 0) {74 fprintf(stderr, "CHILD\n");75 return 0;76 }77 if (pid != waitpid(pid, NULL, 0)) {78 fprintf(stderr, "waitpid failed: %d\n", errno);79 return 1;80 }81 pthread_join(t, NULL);82 fprintf(stderr, "PARENT\n");83 return 0;84}85 86// CHECK: in atfork87// CHECK: in handler88// CHECK: ThreadSanitizer: data race89// CHECK: Write of size 890// CHECK: #0 handler91// CHECK: Previous write of size 892// CHECK: #0 worker93// PARENT: afterfork94// PARENT: in handler95// CHILD: afterfork_child96// CHILD: CHILD97// CHECK: PARENT98