Skip to content

Commit a04db2c

Browse files
[rtsan] Decouple assertions from error actions (#109535)
Decouples sanitizer assertion `ExpectNotRealtime` from the action that should happen if a real-time context is detected.
1 parent cf57a67 commit a04db2c

File tree

5 files changed

+43
-54
lines changed

5 files changed

+43
-54
lines changed

compiler-rt/lib/rtsan/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ include_directories(..)
22

33
set(RTSAN_CXX_SOURCES
44
rtsan.cpp
5-
rtsan_assertions.cpp
65
rtsan_context.cpp
76
rtsan_diagnostics.cpp
87
rtsan_flags.cpp

compiler-rt/lib/rtsan/rtsan.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <rtsan/rtsan.h>
1212
#include <rtsan/rtsan_assertions.h>
13+
#include <rtsan/rtsan_diagnostics.h>
1314
#include <rtsan/rtsan_flags.h>
1415
#include <rtsan/rtsan_interceptors.h>
1516

@@ -28,6 +29,13 @@ static void SetInitialized() {
2829
atomic_store(&rtsan_initialized, 1, memory_order_release);
2930
}
3031

32+
static auto PrintDiagnosticsAndDieAction(DiagnosticsInfo info) {
33+
return [info]() {
34+
__rtsan::PrintDiagnostics(info);
35+
Die();
36+
};
37+
}
38+
3139
extern "C" {
3240

3341
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_init() {
@@ -74,22 +82,21 @@ SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_enable() {
7482
}
7583

7684
SANITIZER_INTERFACE_ATTRIBUTE void
77-
__rtsan_notify_intercepted_call(const char *intercepted_function_name) {
85+
__rtsan_notify_intercepted_call(const char *func_name) {
7886
__rtsan_ensure_initialized();
79-
8087
GET_CALLER_PC_BP;
81-
DiagnosticsInfo info = {InterceptedCallInfo{intercepted_function_name}, pc,
82-
bp};
83-
ExpectNotRealtime(GetContextForThisThread(), info);
88+
ExpectNotRealtime(
89+
GetContextForThisThread(),
90+
PrintDiagnosticsAndDieAction({InterceptedCallInfo{func_name}, pc, bp}));
8491
}
8592

8693
SANITIZER_INTERFACE_ATTRIBUTE void
87-
__rtsan_notify_blocking_call(const char *blocking_function_name) {
94+
__rtsan_notify_blocking_call(const char *func_name) {
8895
__rtsan_ensure_initialized();
89-
9096
GET_CALLER_PC_BP;
91-
DiagnosticsInfo info = {BlockingCallInfo{blocking_function_name}, pc, bp};
92-
ExpectNotRealtime(GetContextForThisThread(), info);
97+
ExpectNotRealtime(
98+
GetContextForThisThread(),
99+
PrintDiagnosticsAndDieAction({BlockingCallInfo{func_name}, pc, bp}));
93100
}
94101

95102
} // extern "C"

compiler-rt/lib/rtsan/rtsan_assertions.cpp

Lines changed: 0 additions & 28 deletions
This file was deleted.

compiler-rt/lib/rtsan/rtsan_assertions.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,19 @@
1212

1313
#pragma once
1414

15+
#include "rtsan/rtsan.h"
1516
#include "rtsan/rtsan_context.h"
16-
#include "rtsan/rtsan_diagnostics.h"
1717

1818
namespace __rtsan {
1919

20-
void ExpectNotRealtime(Context &context, const DiagnosticsInfo &info);
20+
template <typename OnViolationAction>
21+
void ExpectNotRealtime(Context &context, OnViolationAction &&OnViolation) {
22+
CHECK(__rtsan_is_initialized());
23+
if (context.InRealtimeContext() && !context.IsBypassed()) {
24+
context.BypassPush();
25+
OnViolation();
26+
context.BypassPop();
27+
}
28+
}
29+
2130
} // namespace __rtsan

compiler-rt/lib/rtsan/tests/rtsan_test_assertions.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@
1313
#include "rtsan_test_utilities.h"
1414

1515
#include "rtsan/rtsan_assertions.h"
16-
#include "rtsan/rtsan_diagnostics.h"
1716

18-
#include <gtest/gtest.h>
17+
#include <gmock/gmock.h>
1918

2019
using namespace __rtsan;
2120

@@ -24,30 +23,33 @@ class TestRtsanAssertions : public ::testing::Test {
2423
void SetUp() override { __rtsan_ensure_initialized(); }
2524
};
2625

27-
DiagnosticsInfo FakeDiagnosticsInfo() {
28-
DiagnosticsInfo info;
29-
info.pc = 0;
30-
info.bp = 0;
31-
info.call_info = InterceptedCallInfo{"fake_function_name"};
32-
return info;
26+
static void ExpectViolationAction(__rtsan::Context &context,
27+
bool expect_violation_callback) {
28+
::testing::MockFunction<void()> mock_on_violation;
29+
EXPECT_CALL(mock_on_violation, Call).Times(expect_violation_callback ? 1 : 0);
30+
ExpectNotRealtime(context, mock_on_violation.AsStdFunction());
3331
}
3432

35-
TEST_F(TestRtsanAssertions, ExpectNotRealtimeDoesNotDieIfNotInRealtimeContext) {
33+
TEST_F(TestRtsanAssertions,
34+
ExpectNotRealtimeDoesNotCallViolationActionIfNotInRealtimeContext) {
3635
__rtsan::Context context{};
3736
ASSERT_FALSE(context.InRealtimeContext());
38-
ExpectNotRealtime(context, FakeDiagnosticsInfo());
37+
ExpectViolationAction(context, false);
3938
}
4039

41-
TEST_F(TestRtsanAssertions, ExpectNotRealtimeDiesIfInRealtimeContext) {
40+
TEST_F(TestRtsanAssertions,
41+
ExpectNotRealtimeCallsViolationActionIfInRealtimeContext) {
4242
__rtsan::Context context{};
4343
context.RealtimePush();
4444
ASSERT_TRUE(context.InRealtimeContext());
45-
EXPECT_DEATH(ExpectNotRealtime(context, FakeDiagnosticsInfo()), "");
45+
ExpectViolationAction(context, true);
4646
}
4747

48-
TEST_F(TestRtsanAssertions, ExpectNotRealtimeDoesNotDieIfRealtimeButBypassed) {
48+
TEST_F(TestRtsanAssertions,
49+
ExpectNotRealtimeDoesNotCallViolationActionIfRealtimeButBypassed) {
4950
__rtsan::Context context{};
5051
context.RealtimePush();
5152
context.BypassPush();
52-
ExpectNotRealtime(context, FakeDiagnosticsInfo());
53+
ASSERT_TRUE(context.IsBypassed());
54+
ExpectViolationAction(context, false);
5355
}

0 commit comments

Comments
 (0)