[compiler-rt] [TSan][Darwin] Add _longjmp interceptor for Apple platforms (PR #163384)
Dan Blackwell via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 26 04:27:07 PST 2025
https://github.com/DanBlackwell updated https://github.com/llvm/llvm-project/pull/163384
>From e0e752f9c640db63873126a32641a644f3998a31 Mon Sep 17 00:00:00 2001
From: Dan Blackwell <dan_blackwell at apple.com>
Date: Tue, 14 Oct 2025 13:35:59 +0100
Subject: [PATCH] [TSan][Darwin] Add _longjmp interceptor for Apple platforms
As noted in https://github.com/llvm/llvm-project/issues/161443, currently _longjmp is not intercepted. This results in the callstack being incorrect after a call to _longjmp, and in the worst case overflowing with many calls.
This patch adds the missing interceptor, and a test to make sure that the callstack is correctly maintained.
---
.../lib/tsan/rtl/tsan_interceptors_posix.cpp | 2 +-
compiler-rt/test/tsan/setjmp_longjmp.c | 55 +++++++++++++++++++
2 files changed, 56 insertions(+), 1 deletion(-)
create mode 100644 compiler-rt/test/tsan/setjmp_longjmp.c
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index 0c358042d1b56..97a1eed719c84 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -649,7 +649,7 @@ TSAN_INTERCEPTOR(void, siglongjmp_symname, uptr *env, int val) {
REAL(siglongjmp_symname)(env, val);
}
-#if SANITIZER_NETBSD
+#if SANITIZER_NETBSD || SANITIZER_APPLE
TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) {
{
SCOPED_INTERCEPTOR_RAW(_longjmp, env, val);
diff --git a/compiler-rt/test/tsan/setjmp_longjmp.c b/compiler-rt/test/tsan/setjmp_longjmp.c
new file mode 100644
index 0000000000000..ed4d4c9200ec5
--- /dev/null
+++ b/compiler-rt/test/tsan/setjmp_longjmp.c
@@ -0,0 +1,55 @@
+// RUN: %clang_tsan %s -o %t
+// RUN: %deflake %run %t | FileCheck %s
+//
+// XFAIL: {{.*linux.*}}
+
+#include <pthread.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int globalVar;
+
+void foo(jmp_buf *buf, char willExit) {
+ if (willExit)
+ globalVar = 1;
+ _longjmp(*buf, 1);
+}
+
+void func2() {
+ jmp_buf buf;
+ const int reps = 1000;
+ for (int i = 0; i < reps; i++) {
+ if (_setjmp(buf) == 0) {
+ foo(&buf, i == reps - 1);
+ }
+ }
+}
+
+void *writeGlobal(void *ctx) {
+ func2();
+ return NULL;
+}
+
+void *readGlobal(void *ctx) {
+ sleep(1);
+ printf("globalVar: %d\n", globalVar);
+ return NULL;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, writeGlobal, NULL);
+ pthread_create(&t[1], NULL, readGlobal, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Read of size 4 at {{.*}} by thread
+// CHECK: #0 readGlobal
+// CHECK: Previous write of size 4 at {{.*}} by thread
+// CHECK: #0 foo
+// CHECK: #1 func2
+// CHECK: #2 writeGlobal
More information about the llvm-commits
mailing list