Skip to content

Conversation

cjappl
Copy link
Contributor

@cjappl cjappl commented Aug 29, 2025

This fixes #146120, confirmed by the original reporter

Previously reviewed as #155181, but re-submitting for better book-keeping.

Adds versioned pthread_cond interceptors, and the pthread_cond_init/_destroy interceptors

@llvmbot
Copy link
Member

llvmbot commented Aug 29, 2025

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

Author: Chris Apple (cjappl)

Changes

This fixes #146120, confirmed by the original reporter

Previously reviewed as #155181, but re-submitting for better book-keeping.

Adds versioned pthread_cond interceptors, and the pthread_cond_init/_destroy interceptors


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

2 Files Affected:

  • (modified) compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp (+29)
  • (modified) compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp (+18)
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index a9d864e9fe926..eaf2da745f047 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -15,6 +15,7 @@
 
 #include "interception/interception.h"
 #include "sanitizer_common/sanitizer_allocator_dlsym.h"
+#include "sanitizer_common/sanitizer_glibc_version.h"
 #include "sanitizer_common/sanitizer_platform_interceptors.h"
 
 #include "interception/interception.h"
@@ -766,6 +767,12 @@ INTERCEPTOR(int, pthread_join, pthread_t thread, void **value_ptr) {
   return REAL(pthread_join)(thread, value_ptr);
 }
 
+INTERCEPTOR(int, pthread_cond_init, pthread_cond_t *cond,
+            const pthread_condattr_t *a) {
+  __rtsan_notify_intercepted_call("pthread_cond_init");
+  return REAL(pthread_cond_init)(cond, a);
+}
+
 INTERCEPTOR(int, pthread_cond_signal, pthread_cond_t *cond) {
   __rtsan_notify_intercepted_call("pthread_cond_signal");
   return REAL(pthread_cond_signal)(cond);
@@ -788,6 +795,12 @@ INTERCEPTOR(int, pthread_cond_timedwait, pthread_cond_t *cond,
   return REAL(pthread_cond_timedwait)(cond, mutex, ts);
 }
 
+INTERCEPTOR(int, pthread_cond_destroy, pthread_cond_t *cond) {
+  __rtsan_notify_intercepted_call("pthread_cond_destroy");
+  int res = REAL(pthread_cond_destroy)(cond);
+  return res;
+}
+
 INTERCEPTOR(int, pthread_rwlock_rdlock, pthread_rwlock_t *lock) {
   __rtsan_notify_intercepted_call("pthread_rwlock_rdlock");
   return REAL(pthread_rwlock_rdlock)(lock);
@@ -1641,10 +1654,26 @@ void __rtsan::InitializeInterceptors() {
   INTERCEPT_FUNCTION(pthread_mutex_lock);
   INTERCEPT_FUNCTION(pthread_mutex_unlock);
   INTERCEPT_FUNCTION(pthread_join);
+
+  // See the comment in tsan_interceptors_posix.cpp.
+#if SANITIZER_GLIBC && !__GLIBC_PREREQ(2, 36) &&                               \
+    (defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 ||          \
+     defined(__s390x__))
+  INTERCEPT_FUNCTION_VER(pthread_cond_init, "GLIBC_2.3.2");
+  INTERCEPT_FUNCTION_VER(pthread_cond_signal, "GLIBC_2.3.2");
+  INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, "GLIBC_2.3.2");
+  INTERCEPT_FUNCTION_VER(pthread_cond_wait, "GLIBC_2.3.2");
+  INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, "GLIBC_2.3.2");
+  INTERCEPT_FUNCTION_VER(pthread_cond_destroy, "GLIBC_2.3.2");
+#else
+  INTERCEPT_FUNCTION(pthread_cond_init);
   INTERCEPT_FUNCTION(pthread_cond_signal);
   INTERCEPT_FUNCTION(pthread_cond_broadcast);
   INTERCEPT_FUNCTION(pthread_cond_wait);
   INTERCEPT_FUNCTION(pthread_cond_timedwait);
+  INTERCEPT_FUNCTION(pthread_cond_destroy);
+#endif
+
   INTERCEPT_FUNCTION(pthread_rwlock_rdlock);
   INTERCEPT_FUNCTION(pthread_rwlock_unlock);
   INTERCEPT_FUNCTION(pthread_rwlock_wrlock);
diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
index d69a4e74825f0..20e3b485f3be0 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -1241,6 +1241,24 @@ TEST(TestRtsanInterceptors, SpinLockLockDiesWhenRealtime) {
 }
 #endif
 
+TEST(TestRtsanInterceptors, PthreadCondInitDiesWhenRealtime) {
+  pthread_cond_t cond{};
+  auto Func = [&cond]() { pthread_cond_init(&cond, nullptr); };
+  ExpectRealtimeDeath(Func, "pthread_cond_init");
+  ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsanInterceptors, PthreadCondDestroyDiesWhenRealtime) {
+  pthread_cond_t cond{};
+  ASSERT_EQ(0, pthread_cond_init(&cond, nullptr));
+
+  auto Func = [&cond]() { pthread_cond_destroy(&cond); };
+  ExpectRealtimeDeath(Func, "pthread_cond_destroy");
+  ExpectNonRealtimeSurvival(Func);
+
+  pthread_cond_destroy(&cond);
+}
+
 TEST(TestRtsanInterceptors, PthreadCondSignalDiesWhenRealtime) {
   pthread_cond_t cond{};
   ASSERT_EQ(0, pthread_cond_init(&cond, nullptr));

@cjappl
Copy link
Contributor Author

cjappl commented Aug 29, 2025

CC for visibility @adrew0809

Once the PR bot is green, I am going to submit this and cherry pick it to LLVM 21

@@ -788,6 +795,12 @@ INTERCEPTOR(int, pthread_cond_timedwait, pthread_cond_t *cond,
return REAL(pthread_cond_timedwait)(cond, mutex, ts);
}

INTERCEPTOR(int, pthread_cond_destroy, pthread_cond_t *cond) {
__rtsan_notify_intercepted_call("pthread_cond_destroy");
int res = REAL(pthread_cond_destroy)(cond);
Copy link
Member

Choose a reason for hiding this comment

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

return REAL(...)...

@cjappl cjappl merged commit 8f317c1 into llvm:main Aug 29, 2025
7 of 9 checks passed
@cjappl
Copy link
Contributor Author

cjappl commented Aug 29, 2025

Giving it a few hours to run through some CI, then will cherry pick by EOD

@cjappl cjappl deleted the cjappl/version_pthread_cond_interceptors branch August 29, 2025 18:06
@cjappl
Copy link
Contributor Author

cjappl commented Aug 30, 2025

/cherry-pick 8f317c1

@llvmbot
Copy link
Member

llvmbot commented Aug 30, 2025

/cherry-pick

Error: Command failed due to missing milestone.

@llvmbot
Copy link
Member

llvmbot commented Aug 30, 2025

/cherry-pick 8f317c1

Error: Command failed due to missing milestone.

@cjappl
Copy link
Contributor Author

cjappl commented Aug 30, 2025

/cherry-pick 8f317c1

(Take 2, sorry, this is my first time trying this process out)

@llvmbot
Copy link
Member

llvmbot commented Aug 30, 2025

/pull-request #156196

@llvmbot llvmbot moved this from Needs Triage to Done in LLVM Release Status Aug 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

Real-time Sanitizer causes pthread_cond_signal to segfault when a thread is doing a timed wait on a condition variable
4 participants