-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[rtsan][Apple] Add interceptor for _os_nospin_lock_lock #131034
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
[rtsan][Apple] Add interceptor for _os_nospin_lock_lock #131034
Conversation
@llvm/pr-subscribers-compiler-rt-sanitizer Author: None (davidtrevelyan) ChangesFollows the discussion here: #129309 Recently, the test This PR introduces an interceptor for Full diff: https://github.com/llvm/llvm-project/pull/131034.diff 2 Files Affected:
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index cd57107450a47..5bbefa3ce43f1 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -30,6 +30,12 @@
extern "C" {
typedef int32_t OSSpinLock;
void OSSpinLockLock(volatile OSSpinLock *__lock);
+// A pointer to this type is in the interface for `_os_nospin_lock_lock`, but
+// it's an internal implementation detail of `os/lock.c` on Darwin, and
+// therefore not available in any headers. As a workaround, we forward declare
+// it here, which is enough to facilitate interception of _os_nospin_lock_lock.
+struct _os_nospin_lock_s;
+using _os_nospin_lock_t = _os_nospin_lock_s *;
}
#endif // TARGET_OS_MAC
@@ -711,6 +717,11 @@ INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
__rtsan_notify_intercepted_call("os_unfair_lock_lock");
return REAL(os_unfair_lock_lock)(lock);
}
+
+INTERCEPTOR(void, _os_nospin_lock_lock, _os_nospin_lock_t lock) {
+ __rtsan_notify_intercepted_call("_os_nospin_lock_lock");
+ return REAL(_os_nospin_lock_lock)(lock);
+}
#define RTSAN_MAYBE_INTERCEPT_OS_UNFAIR_LOCK_LOCK \
INTERCEPT_FUNCTION(os_unfair_lock_lock)
#else
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 47bcafff51a4d..9ef6887a9c848 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -1122,6 +1122,25 @@ TEST(TestRtsanInterceptors, OsUnfairLockLockDiesWhenRealtime) {
ExpectRealtimeDeath(Func, "os_unfair_lock_lock");
ExpectNonRealtimeSurvival(Func);
}
+
+// We intercept _os_nospin_lock_lock because it's the internal
+// locking mechanism for MacOS's atomic implementation for data
+// types that are larger than the hardware's maximum lock-free size.
+// However, it's a private implementation detail and not visible in any headers,
+// so we must duplicate the required type definitions to forward declaration
+// what we need here.
+extern "C" {
+struct _os_nospin_lock_s {
+ unsigned int oul_value;
+};
+void _os_nospin_lock_lock(_os_nospin_lock_s *);
+}
+TEST(TestRtsanInterceptors, OsNoSpinLockLockDiesWhenRealtime) {
+ _os_nospin_lock_s lock{};
+ auto Func = [&]() { _os_nospin_lock_lock(&lock); };
+ ExpectRealtimeDeath(Func, "_os_nospin_lock_lock");
+ ExpectNonRealtimeSurvival(Func);
+}
#endif
#if SANITIZER_LINUX
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM thanks for your legwork on this one
Also if this is merged and tests are happy, we may consider cherry picking to the llvm 20 release branch as this is "expected behavior" for that version. It would be good to get in the next release if we feel good about it. |
Thanks to both of you. Note for your future development that these locks come in bundles, as do unfair locks: |
In a follow-up you can you please wrap this with:
|
@thetruestblue sure - no problem. Which section(s) of code in this patch are you referring to wrapping here? If you'd find it easier to submit a PR to describe this, I'd be very happy to take a look. @delcypher are you by any chance able to share details about how this broke your build? |
@davidtrevelyan Unfortunately it fails in a way that you won't be able to reproduce because the build fails when using Apple's internal SDKs which are different from the public ones. The error looks like this. I've had to redact a few things.
|
@davidtrevelyan @thetruestblue Doing this fixed the build for me using the internal SDK.
|
Follows the discussion here: llvm#129309 Recently, the test `TestRtsan.AccessingALargeAtomicVariableDiesWhenRealtime` has been failing on newer MacOS versions, because the internal locking mechanism in `std::atomic<T>::load` (for types `T` that are larger than the hardware lock-free limit), has changed to a function that wasn't being intercepted by rtsan. This PR introduces an interceptor for `_os_nospin_lock_lock`, which is the new internal locking mechanism. _Note: we'd probably do well to introduce interceptors for `_os_nospin_lock_unlock` (and `os_unfair_lock_unlock`) too, which also appear to have blocking implementations. This can follow in a separate PR._
/cherry-pick 6f99abc |
Cherry-picked to LLVM 20, as the tests are still failing on LLVM 20 release bot |
Failed to cherry-pick: 6f99abc https://github.com/llvm/llvm-project/actions/runs/14069840627 Please manually backport the fix and push it to your github fork. Once this is done, please create a pull request |
/cherry-pick 481a55a |
/pull-request #132997 |
Follows the discussion here: llvm#129309 Recently, the test `TestRtsan.AccessingALargeAtomicVariableDiesWhenRealtime` has been failing on newer MacOS versions, because the internal locking mechanism in `std::atomic<T>::load` (for types `T` that are larger than the hardware lock-free limit), has changed to a function that wasn't being intercepted by rtsan. This PR introduces an interceptor for `_os_nospin_lock_lock`, which is the new internal locking mechanism. _Note: we'd probably do well to introduce interceptors for `_os_nospin_lock_unlock` (and `os_unfair_lock_unlock`) too, which also appear to have blocking implementations. This can follow in a separate PR._ (cherry picked from commit 481a55a)
Failed to cherry-pick: 6f99abc https://github.com/llvm/llvm-project/actions/runs/14737412738 Please manually backport the fix and push it to your github fork. Once this is done, please create a pull request |
Follows the discussion here: llvm#129309 Recently, the test `TestRtsan.AccessingALargeAtomicVariableDiesWhenRealtime` has been failing on newer MacOS versions, because the internal locking mechanism in `std::atomic<T>::load` (for types `T` that are larger than the hardware lock-free limit), has changed to a function that wasn't being intercepted by rtsan. This PR introduces an interceptor for `_os_nospin_lock_lock`, which is the new internal locking mechanism. _Note: we'd probably do well to introduce interceptors for `_os_nospin_lock_unlock` (and `os_unfair_lock_unlock`) too, which also appear to have blocking implementations. This can follow in a separate PR._ (cherry picked from commit 481a55a)
Follows the discussion here: #129309
Recently, the test
TestRtsan.AccessingALargeAtomicVariableDiesWhenRealtime
has been failing on newer MacOS versions, because the internal locking mechanism instd::atomic<T>::load
(for typesT
that are larger than the hardware lock-free limit), has changed to a function that wasn't being intercepted by rtsan.This PR introduces an interceptor for
_os_nospin_lock_lock
, which is the new internal locking mechanism.Note: we'd probably do well to introduce interceptors for
_os_nospin_lock_unlock
(andos_unfair_lock_unlock
) too, which also appear to have blocking implementations. This can follow in a separate PR.