1*7c3d14c8STreehugger Robot // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
2*7c3d14c8STreehugger Robot #include "test.h"
3*7c3d14c8STreehugger Robot #include <signal.h>
4*7c3d14c8STreehugger Robot #include <unistd.h>
5*7c3d14c8STreehugger Robot #include <errno.h>
6*7c3d14c8STreehugger Robot #include <semaphore.h>
7*7c3d14c8STreehugger Robot
8*7c3d14c8STreehugger Robot // Test that signals can be delivered to blocked pthread_cond_wait.
9*7c3d14c8STreehugger Robot // https://github.com/google/sanitizers/issues/498
10*7c3d14c8STreehugger Robot
11*7c3d14c8STreehugger Robot int g_thread_run = 1;
12*7c3d14c8STreehugger Robot pthread_mutex_t mutex;
13*7c3d14c8STreehugger Robot pthread_cond_t cond;
14*7c3d14c8STreehugger Robot
sig_handler(int sig)15*7c3d14c8STreehugger Robot void sig_handler(int sig) {
16*7c3d14c8STreehugger Robot (void)sig;
17*7c3d14c8STreehugger Robot write(1, "SIGNAL\n", sizeof("SIGNAL\n") - 1);
18*7c3d14c8STreehugger Robot barrier_wait(&barrier);
19*7c3d14c8STreehugger Robot }
20*7c3d14c8STreehugger Robot
my_thread(void * arg)21*7c3d14c8STreehugger Robot void* my_thread(void* arg) {
22*7c3d14c8STreehugger Robot pthread_mutex_lock(&mutex);
23*7c3d14c8STreehugger Robot while (g_thread_run)
24*7c3d14c8STreehugger Robot pthread_cond_wait(&cond, &mutex);
25*7c3d14c8STreehugger Robot pthread_mutex_unlock(&mutex);
26*7c3d14c8STreehugger Robot return 0;
27*7c3d14c8STreehugger Robot }
28*7c3d14c8STreehugger Robot
main()29*7c3d14c8STreehugger Robot int main() {
30*7c3d14c8STreehugger Robot barrier_init(&barrier, 2);
31*7c3d14c8STreehugger Robot
32*7c3d14c8STreehugger Robot pthread_mutex_init(&mutex, 0);
33*7c3d14c8STreehugger Robot pthread_cond_init(&cond, 0);
34*7c3d14c8STreehugger Robot
35*7c3d14c8STreehugger Robot signal(SIGUSR1, &sig_handler);
36*7c3d14c8STreehugger Robot pthread_t thr;
37*7c3d14c8STreehugger Robot pthread_create(&thr, 0, &my_thread, 0);
38*7c3d14c8STreehugger Robot // wait for thread to get inside pthread_cond_wait
39*7c3d14c8STreehugger Robot // (can't use barrier_wait for that)
40*7c3d14c8STreehugger Robot sleep(1);
41*7c3d14c8STreehugger Robot pthread_kill(thr, SIGUSR1);
42*7c3d14c8STreehugger Robot barrier_wait(&barrier);
43*7c3d14c8STreehugger Robot pthread_mutex_lock(&mutex);
44*7c3d14c8STreehugger Robot g_thread_run = 0;
45*7c3d14c8STreehugger Robot pthread_cond_signal(&cond);
46*7c3d14c8STreehugger Robot pthread_mutex_unlock(&mutex);
47*7c3d14c8STreehugger Robot pthread_join(thr, 0);
48*7c3d14c8STreehugger Robot fprintf(stderr, "DONE\n");
49*7c3d14c8STreehugger Robot return 0;
50*7c3d14c8STreehugger Robot }
51*7c3d14c8STreehugger Robot
52*7c3d14c8STreehugger Robot // CHECK: SIGNAL
53*7c3d14c8STreehugger Robot // CHECK: DONE
54