1 // RUN: %clangxx_tsan %s -o %t && %run %t 2>&1 | FileCheck %s
10 #include <sys/select.h>
12 #include <sys/types.h>
15 // This attempts to exercise a race condition where both a thread and its signal
16 // handler allocate the SigCtx. If the race is allowed, it leads to a leak and
17 // the first signal being dropped.
18 // Spawn threads in a loop and send it SIGUSR1 concurrently with the thread
19 // doing a bogus kill() call. The signal handler writes to a self-pipe which the
20 // thread detects and then exits. A dropped signal results in a timeout.
22 static void handler(int sig
) { write(pipes
[1], "x", 1); }
24 static int do_select() {
30 FD_SET(pipes
[0], &fds
);
31 return select(pipes
[0] + 1, &fds
, 0, 0, &tvs
);
34 static void *thr(void *p
) {
35 // This kill() is expected to fail; it exists only to trigger a call to SigCtx
36 // outside of the signal handler.
39 for (int i
= 0; i
< 1024; i
++) {
40 if (do_select() > 0) {
47 read(pipes
[0], &c
, 1);
49 fprintf(stderr
, "Failed to receive signal\n");
61 struct sigaction act
= {};
62 act
.sa_handler
= &handler
;
63 if (sigaction(SIGUSR1
, &act
, 0)) {
68 for (int i
= 0; i
< (1 << 10); i
++) {
70 if (pthread_create(&th
, 0, thr
, 0)) {
71 perror("pthread_create");
74 pthread_kill(th
, SIGUSR1
);
78 fprintf(stderr
, "DONE\n");
82 // CHECK-NOT: WARNING: ThreadSanitizer:
84 // CHECK-NOT: WARNING: ThreadSanitizer: