diff options
author | Julian Lettner <yln@users.noreply.github.com> | 2024-05-17 13:58:34 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-17 13:58:34 -0700 |
commit | 1a5bc7c895ddeafa0e1d269da67bbeafcd8bc1a4 (patch) | |
tree | 6abcb965f2084eccbb07b645c04731f537236517 | |
parent | af7467ce9f447d6fe977b73db1f03a18d6bbd511 (diff) | |
download | llvm-1a5bc7c895ddeafa0e1d269da67bbeafcd8bc1a4.zip llvm-1a5bc7c895ddeafa0e1d269da67bbeafcd8bc1a4.tar.gz llvm-1a5bc7c895ddeafa0e1d269da67bbeafcd8bc1a4.tar.bz2 |
Fix flaky test: signal_in_mutex_lock.cpp (#92587)
Fix flaky test: the spawned thread keeps spinning
on `sampler_mutex` which may be released before
the thread is terminated based on termination
ordering.
My understanding of C++ semantics are that the
program here is invalid: the destructors of global
variables are invoked at the time of program
termination, and it is the responsibility of the
program to ensure that invoking those destructors
is safe.
rdar://126768628
-rw-r--r-- | compiler-rt/test/tsan/signal_in_mutex_lock.cpp | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/compiler-rt/test/tsan/signal_in_mutex_lock.cpp b/compiler-rt/test/tsan/signal_in_mutex_lock.cpp index ec99e23..49b8536 100644 --- a/compiler-rt/test/tsan/signal_in_mutex_lock.cpp +++ b/compiler-rt/test/tsan/signal_in_mutex_lock.cpp @@ -5,6 +5,7 @@ #include <signal.h> #include <stdio.h> +#include <atomic> #include <cassert> #include <condition_variable> #include <mutex> @@ -13,9 +14,10 @@ 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; +std::atomic<bool> spin = true; void *ThreadFunc(void *x) { - while (true) { + while (spin) { // Lock the mutex std::lock_guard<std::mutex> guard(sampler_mutex); // Mutex is released at the end @@ -51,20 +53,26 @@ int main() { 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 + { + // 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); + // 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; }); + // 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"); + } - // We got the done variable from the signal handler. Exiting successfully. - fprintf(stderr, "PASS\n"); + // Wait for thread to prevent it from spinning on a released mutex. + spin = false; + pthread_join(thread, nullptr); } // CHECK-NOT: WARNING: ThreadSanitizer: |