[compiler-rt] [rtsan] Support legacy pthread_cond variables (PR #152947)
Chris Apple via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 11 10:45:03 PDT 2025
https://github.com/cjappl updated https://github.com/llvm/llvm-project/pull/152947
>From c9708f8ef671e3c7e5a545cd009de2c2eece94cf Mon Sep 17 00:00:00 2001
From: Chris Apple <cja-private at pm.me>
Date: Sat, 26 Jul 2025 16:03:56 -0700
Subject: [PATCH 1/2] [rtsan] Support legacy pthread_cond variables
---
.../lib/rtsan/rtsan_interceptors_posix.cpp | 75 +++++++++++++++++--
1 file changed, 67 insertions(+), 8 deletions(-)
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index a9d864e9fe926..b37229f39a453 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -46,12 +46,44 @@
using namespace __sanitizer;
+#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
+ defined(__s390x__)
+#define PTHREAD_ABI_BASE "GLIBC_2.3.2"
+#elif defined(__aarch64__) || SANITIZER_PPC64V2
+#define PTHREAD_ABI_BASE "GLIBC_2.17"
+#elif SANITIZER_LOONGARCH64
+#define PTHREAD_ABI_BASE "GLIBC_2.36"
+#elif SANITIZER_RISCV64
+#define PTHREAD_ABI_BASE "GLIBC_2.27"
+#endif
+
+DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, usize size)
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
+
namespace {
struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
static bool UseImpl() { return !__rtsan_is_initialized(); }
};
} // namespace
+// See note in tsan or ddsan as to why this is necessary
+static pthread_cond_t *init_cond(pthread_cond_t *c, bool force = false) {
+ if (!common_flags()->legacy_pthread_cond)
+ return c;
+
+ atomic_uintptr_t *p = (atomic_uintptr_t *)c;
+ uptr cond = atomic_load(p, memory_order_acquire);
+ if (!force && cond != 0)
+ return (pthread_cond_t *)cond;
+ void *newcond = WRAP(malloc)(sizeof(pthread_cond_t));
+ internal_memset(newcond, 0, sizeof(pthread_cond_t));
+ if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond,
+ memory_order_acq_rel))
+ return (pthread_cond_t *)newcond;
+ WRAP(free)(newcond);
+ return (pthread_cond_t *)cond;
+}
+
// Filesystem
INTERCEPTOR(int, open, const char *path, int oflag, ...) {
@@ -766,26 +798,49 @@ 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");
+ pthread_cond_t *c = init_cond(cond, true);
+ return REAL(pthread_cond_init)(c, a);
+}
+
INTERCEPTOR(int, pthread_cond_signal, pthread_cond_t *cond) {
__rtsan_notify_intercepted_call("pthread_cond_signal");
- return REAL(pthread_cond_signal)(cond);
+ pthread_cond_t *c = init_cond(cond);
+ return REAL(pthread_cond_signal)(c);
}
INTERCEPTOR(int, pthread_cond_broadcast, pthread_cond_t *cond) {
__rtsan_notify_intercepted_call("pthread_cond_broadcast");
- return REAL(pthread_cond_broadcast)(cond);
+ pthread_cond_t *c = init_cond(cond);
+ return REAL(pthread_cond_broadcast)(c);
}
INTERCEPTOR(int, pthread_cond_wait, pthread_cond_t *cond,
pthread_mutex_t *mutex) {
__rtsan_notify_intercepted_call("pthread_cond_wait");
- return REAL(pthread_cond_wait)(cond, mutex);
+ pthread_cond_t *c = init_cond(cond);
+ return REAL(pthread_cond_wait)(c, mutex);
}
INTERCEPTOR(int, pthread_cond_timedwait, pthread_cond_t *cond,
pthread_mutex_t *mutex, const timespec *ts) {
__rtsan_notify_intercepted_call("pthread_cond_timedwait");
- return REAL(pthread_cond_timedwait)(cond, mutex, ts);
+ pthread_cond_t *c = init_cond(cond);
+ return REAL(pthread_cond_timedwait)(c, mutex, ts);
+}
+
+INTERCEPTOR(int, pthread_cond_destroy, pthread_cond_t *cond) {
+ __rtsan_notify_intercepted_call("pthread_cond_destroy");
+ pthread_cond_t *c = init_cond(cond);
+ int res = REAL(pthread_cond_destroy)(c);
+ if (common_flags()->legacy_pthread_cond) {
+ // Free our aux cond and zero the pointer to not leave dangling pointers.
+ WRAP(free)(c);
+ atomic_store((atomic_uintptr_t *)c, 0, memory_order_relaxed);
+ }
+ return res;
}
INTERCEPTOR(int, pthread_rwlock_rdlock, pthread_rwlock_t *lock) {
@@ -1641,10 +1696,14 @@ void __rtsan::InitializeInterceptors() {
INTERCEPT_FUNCTION(pthread_mutex_lock);
INTERCEPT_FUNCTION(pthread_mutex_unlock);
INTERCEPT_FUNCTION(pthread_join);
- INTERCEPT_FUNCTION(pthread_cond_signal);
- INTERCEPT_FUNCTION(pthread_cond_broadcast);
- INTERCEPT_FUNCTION(pthread_cond_wait);
- INTERCEPT_FUNCTION(pthread_cond_timedwait);
+
+ INTERCEPT_FUNCTION_VER(pthread_cond_init, PTHREAD_ABI_BASE);
+ INTERCEPT_FUNCTION_VER(pthread_cond_signal, PTHREAD_ABI_BASE);
+ INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, PTHREAD_ABI_BASE);
+ INTERCEPT_FUNCTION_VER(pthread_cond_wait, PTHREAD_ABI_BASE);
+ INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, PTHREAD_ABI_BASE);
+ INTERCEPT_FUNCTION_VER(pthread_cond_destroy, PTHREAD_ABI_BASE);
+
INTERCEPT_FUNCTION(pthread_rwlock_rdlock);
INTERCEPT_FUNCTION(pthread_rwlock_unlock);
INTERCEPT_FUNCTION(pthread_rwlock_wrlock);
>From 7aa16b5e5c19bb2f38d3ca9a19433824bf216be1 Mon Sep 17 00:00:00 2001
From: Chris Apple <cja-private at pm.me>
Date: Mon, 11 Aug 2025 10:44:51 -0700
Subject: [PATCH 2/2] PR: Make 'destroy_cond' helper
---
compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index b37229f39a453..7879d20ccab25 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -84,6 +84,14 @@ static pthread_cond_t *init_cond(pthread_cond_t *c, bool force = false) {
return (pthread_cond_t *)cond;
}
+static void destroy_cond(pthread_cond_t *cond) {
+ if (common_flags()->legacy_pthread_cond) {
+ // Free our aux cond and zero the pointer to not leave dangling pointers.
+ WRAP(free)(cond);
+ atomic_store((atomic_uintptr_t *)cond, 0, memory_order_relaxed);
+ }
+}
+
// Filesystem
INTERCEPTOR(int, open, const char *path, int oflag, ...) {
@@ -835,11 +843,7 @@ INTERCEPTOR(int, pthread_cond_destroy, pthread_cond_t *cond) {
__rtsan_notify_intercepted_call("pthread_cond_destroy");
pthread_cond_t *c = init_cond(cond);
int res = REAL(pthread_cond_destroy)(c);
- if (common_flags()->legacy_pthread_cond) {
- // Free our aux cond and zero the pointer to not leave dangling pointers.
- WRAP(free)(c);
- atomic_store((atomic_uintptr_t *)c, 0, memory_order_relaxed);
- }
+ destroy_cond(c);
return res;
}
More information about the llvm-commits
mailing list