|  | // RUN: %clang_tsan %s -lstdc++ -o %t && %run %t 2>&1 | FileCheck %s | 
|  |  | 
|  | #include "test.h" | 
|  | #include <pthread.h> | 
|  | #include <signal.h> | 
|  | #include <stdio.h> | 
|  |  | 
|  | #include <cassert> | 
|  | #include <condition_variable> | 
|  | #include <mutex> | 
|  |  | 
|  | std::mutex sampler_mutex; //dummy mutex to lock in the thread we spawn. | 
|  | std::mutex done_mutex;    // guards the cv and done variables. | 
|  | std::condition_variable cv; | 
|  | bool done = false; | 
|  |  | 
|  | void *ThreadFunc(void *x) { | 
|  | while (true) { | 
|  | // Lock the mutex | 
|  | std::lock_guard<std::mutex> guard(sampler_mutex); | 
|  | // Mutex is released at the end | 
|  | } | 
|  |  | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | static void SigprofHandler(int signal, siginfo_t *info, void *context) { | 
|  | // Assuming we did some work, change the variable to let the main thread | 
|  | // know that we are done. | 
|  | { | 
|  | std::unique_lock<std::mutex> lck(done_mutex); | 
|  | done = true; | 
|  | cv.notify_one(); | 
|  | } | 
|  | } | 
|  |  | 
|  | int main() { | 
|  | alarm(60); // Kill the test if it hangs. | 
|  |  | 
|  | // Install the signal handler | 
|  | struct sigaction sa; | 
|  | sa.sa_sigaction = SigprofHandler; | 
|  | sigemptyset(&sa.sa_mask); | 
|  | sa.sa_flags = SA_RESTART | SA_SIGINFO; | 
|  | if (sigaction(SIGPROF, &sa, 0) != 0) { | 
|  | fprintf(stderr, "failed to install signal handler\n"); | 
|  | abort(); | 
|  | } | 
|  |  | 
|  | // Spawn a thread that will just loop and get the mutex lock: | 
|  | pthread_t thread; | 
|  | pthread_create(&thread, NULL, ThreadFunc, NULL); | 
|  |  | 
|  | // Lock the mutex before sending the signal | 
|  | std::lock_guard<std::mutex> guard(sampler_mutex); | 
|  | // From now on thread 1 will be waiting for the lock | 
|  |  | 
|  | // Send the SIGPROF signal to thread. | 
|  | int r = pthread_kill(thread, SIGPROF); | 
|  | assert(r == 0); | 
|  |  | 
|  | // Wait until signal handler sends the data. | 
|  | std::unique_lock lk(done_mutex); | 
|  | cv.wait(lk, [] { return done; }); | 
|  |  | 
|  | // We got the done variable from the signal handler. Exiting successfully. | 
|  | fprintf(stderr, "PASS\n"); | 
|  | } | 
|  |  | 
|  | // CHECK-NOT: WARNING: ThreadSanitizer: | 
|  | // CHECK: PASS |