Skip to content

Fix flaky test: signal_in_mutex_lock.cpp #92587

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 17, 2024

Conversation

yln
Copy link
Collaborator

@yln yln commented May 17, 2024

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

@llvmbot
Copy link
Member

llvmbot commented May 17, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Julian Lettner (yln)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/92587.diff

1 Files Affected:

  • (modified) compiler-rt/test/tsan/signal_in_mutex_lock.cpp (+19-12)
diff --git a/compiler-rt/test/tsan/signal_in_mutex_lock.cpp b/compiler-rt/test/tsan/signal_in_mutex_lock.cpp
index ec99e23198400..7795351213d2a 100644
--- a/compiler-rt/test/tsan/signal_in_mutex_lock.cpp
+++ b/compiler-rt/test/tsan/signal_in_mutex_lock.cpp
@@ -13,9 +13,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 +52,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:

@yln yln requested review from wrotki and thetruestblue May 17, 2024 18:32
@yln
Copy link
Collaborator Author

yln commented May 17, 2024

Test added in #84162. @canova

Seeing flaky failures for this test:
https://green.lab.llvm.org/job/llvm.org/job/clang-stage1-RA/780/testReport/junit/ThreadSanitizer-x86_64h/ThreadSanitizer-x86_64h/signal_in_mutex_lock_cpp/

(lldb) bt all
  thread #1, queue = 'com.apple.main-thread'
    ...
    frame #5: 0x000000018bfb67ec libsystem_c.dylib`__cxa_finalize_ranges + 476
    frame #6: 0x000000018bfb65b0 libsystem_c.dylib`exit + 44
    frame #7: 0x000000018c11ed58 libdyld.dylib`dyld4::LibSystemHelpers::exit(int) const + 20
    frame #8: 0x000000018bd722e4 dyld`start + 2952
* thread #3, stop reason = signal SIGABRT
  * frame #0: 0x000000018c0c2540 libsystem_kernel.dylib`__pthread_kill + 8
    ...
    frame #11: 0x000000018c030a44 libc++.1.dylib`std::__1::__throw_system_error[abi:ne180100](std::__1::error_code, char const*) + 92
    frame #12: 0x000000018c0309e8 libc++.1.dylib`std::__1::__throw_system_error(int, char const*) + 48
    frame #13: 0x000000018c032770 libc++.1.dylib`std::__1::mutex::lock() + 40
    frame #14: 0x00000001000033f0 signal_in_mutex_lock.cpp.tmp`::lock_guard() at lock_guard.h:35:10
    frame #15: 0x0000000100002f40 signal_in_mutex_lock.cpp.tmp`::lock_guard() at lock_guard.h:34:19
    frame #16: 0x0000000100002ed8 signal_in_mutex_lock.cpp.tmp`::ThreadFunc() at signal_in_mutex_lock.cpp:20:33
    frame #17: 0x00000001004da828 libclang_rt.tsan_osx_dynamic.dylib`__tsan_thread_start_func(arg=0x000000016fdfefd8) at tsan_interceptors_posix.cpp:1013:15 [opt]
    frame #18: 0x000000018c0faf40 libsystem_pthread.dylib`_pthread_start + 136

Mutex is destroyed from main thread (__cxa_finalize_ranges()) while the created thread is still spinning on it.

@yln yln self-assigned this May 17, 2024
Copy link
Contributor

@wrotki wrotki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

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
@yln yln force-pushed the users/signal_in_mutex_lock.cpp-test-fix branch from d4e3e17 to 84c8627 Compare May 17, 2024 19:12
@yln yln merged commit 1a5bc7c into main May 17, 2024
4 checks passed
@yln yln deleted the users/signal_in_mutex_lock.cpp-test-fix branch May 17, 2024 20:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants