Skip to content

Commit 0a2a319

Browse files
authored
[rtsan] Make sure rtsan gets initialized on mac (llvm#100188)
Intermittently on my mac I was getting the same nullptr crash in dlsym. We need to make sure rtsan gets initialized on mac between when the binary starts running, and the first intercepted function is called. Until that point we should use the DlsymAllocator.
1 parent b7c7dbd commit 0a2a319

File tree

3 files changed

+37
-19
lines changed

3 files changed

+37
-19
lines changed

compiler-rt/lib/rtsan/rtsan.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,42 @@
1212
#include <rtsan/rtsan_context.h>
1313
#include <rtsan/rtsan_interceptors.h>
1414

15+
#include "sanitizer_common/sanitizer_atomic.h"
16+
#include "sanitizer_common/sanitizer_mutex.h"
17+
1518
using namespace __rtsan;
19+
using namespace __sanitizer;
20+
21+
static StaticSpinMutex rtsan_inited_mutex;
22+
static atomic_uint8_t rtsan_initialized = {0};
1623

17-
bool __rtsan::rtsan_initialized;
18-
bool __rtsan::rtsan_init_is_running;
24+
static void SetInitialized() {
25+
atomic_store(&rtsan_initialized, 1, memory_order_release);
26+
}
1927

2028
extern "C" {
2129

2230
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_init() {
23-
CHECK(!rtsan_init_is_running);
24-
if (rtsan_initialized)
31+
CHECK(!__rtsan_is_initialized());
32+
InitializeInterceptors();
33+
SetInitialized();
34+
}
35+
36+
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_ensure_initialized() {
37+
if (LIKELY(__rtsan_is_initialized()))
2538
return;
26-
rtsan_init_is_running = true;
2739

28-
InitializeInterceptors();
40+
SpinMutexLock lock(&rtsan_inited_mutex);
41+
42+
// Someone may have initialized us while we were waiting for the lock
43+
if (__rtsan_is_initialized())
44+
return;
45+
46+
__rtsan_init();
47+
}
2948

30-
rtsan_init_is_running = false;
31-
rtsan_initialized = true;
49+
SANITIZER_INTERFACE_ATTRIBUTE bool __rtsan_is_initialized() {
50+
return atomic_load(&rtsan_initialized, memory_order_acquire) == 1;
3251
}
3352

3453
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_enter() {

compiler-rt/lib/rtsan/rtsan.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@
1414

1515
extern "C" {
1616

17-
namespace __rtsan {
18-
19-
extern bool rtsan_initialized;
20-
extern bool rtsan_init_is_running;
21-
22-
} // namespace __rtsan
23-
2417
// Initialise rtsan interceptors.
2518
// A call to this method is added to the preinit array on Linux systems.
2619
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_init();
2720

21+
// Initializes rtsan if it has not been initialized yet.
22+
// Used by the RTSan runtime to ensure that rtsan is initialized before any
23+
// other rtsan functions are called.
24+
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_ensure_initialized();
25+
26+
SANITIZER_INTERFACE_ATTRIBUTE bool __rtsan_is_initialized();
27+
2828
// Enter real-time context.
2929
// When in a real-time context, RTSan interceptors will error if realtime
3030
// violations are detected. Calls to this method are injected at the code

compiler-rt/lib/rtsan/rtsan_interceptors.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,15 @@ void OSSpinLockLock(volatile OSSpinLock *__lock);
5151

5252
using namespace __sanitizer;
5353

54-
using __rtsan::rtsan_init_is_running;
55-
using __rtsan::rtsan_initialized;
56-
5754
namespace {
5855
struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
59-
static bool UseImpl() { return !rtsan_initialized; }
56+
static bool UseImpl() { return !__rtsan_is_initialized(); }
6057
};
6158
} // namespace
6259

6360
void ExpectNotRealtime(const char *intercepted_function_name) {
61+
__rtsan_ensure_initialized();
62+
6463
__rtsan::GetContextForThisThread().ExpectNotRealtime(
6564
intercepted_function_name);
6665
}

0 commit comments

Comments
 (0)