Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion compiler-rt/lib/rtsan/rtsan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_mutex.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_stacktrace.h"

using namespace __rtsan;
Expand Down Expand Up @@ -49,7 +50,30 @@ static auto OnViolationAction(DiagnosticsInfo info) {
return [info]() {
IncrementTotalErrorCount();

PrintDiagnostics(info);
BufferedStackTrace stack;

// We use the unwind_on_fatal flag here because of precedent with other
// sanitizers, this action is not necessarily fatal if halt_on_error=false
stack.Unwind(info.pc, info.bp, nullptr,
common_flags()->fast_unwind_on_fatal);

// If in the future we interop with other sanitizers, we will
// need to make our own stackdepot
StackDepotHandle handle = StackDepotPut_WithHandle(stack);

const bool is_stack_novel = handle.use_count() == 0;

// Marked UNLIKELY as if user is runing with halt_on_error=false
// we expect a high number of duplicate stacks. We are willing
// To pay for the first insertion.
if (UNLIKELY(is_stack_novel)) {
IncrementUniqueErrorCount();

PrintDiagnostics(info);
stack.Print();

handle.inc_use_count_unsafe();
}

if (flags().halt_on_error)
Die();
Expand Down
8 changes: 0 additions & 8 deletions compiler-rt/lib/rtsan/rtsan_diagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,6 @@ class Decorator : public __sanitizer::SanitizerCommonDecorator {
};
} // namespace

static void PrintStackTrace(uptr pc, uptr bp) {
BufferedStackTrace stack{};

stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal);
stack.Print();
}

static void PrintError(const Decorator &decorator,
const DiagnosticsInfo &info) {
const auto ErrorTypeStr = [&info]() -> const char * {
Expand Down Expand Up @@ -91,5 +84,4 @@ void __rtsan::PrintDiagnostics(const DiagnosticsInfo &info) {
PrintError(d, info);
PrintReason(d, info);
Printf("%s", d.Default());
PrintStackTrace(info.pc, info.bp);
}
10 changes: 10 additions & 0 deletions compiler-rt/lib/rtsan/rtsan_stats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,27 @@ using namespace __sanitizer;
using namespace __rtsan;

static atomic_uint32_t rtsan_total_error_count{0};
static atomic_uint32_t rtsan_unique_error_count{0};

void __rtsan::IncrementTotalErrorCount() {
atomic_fetch_add(&rtsan_total_error_count, 1, memory_order_relaxed);
}

void __rtsan::IncrementUniqueErrorCount() {
atomic_fetch_add(&rtsan_unique_error_count, 1, memory_order_relaxed);
}

static u32 GetTotalErrorCount() {
return atomic_load(&rtsan_total_error_count, memory_order_relaxed);
}

static u32 GetUniqueErrorCount() {
return atomic_load(&rtsan_unique_error_count, memory_order_relaxed);
}

void __rtsan::PrintStatisticsSummary() {
ScopedErrorReportLock l;
Printf("RealtimeSanitizer exit stats:\n");
Printf(" Total error count: %u\n", GetTotalErrorCount());
Printf(" Unique error count: %u\n", GetUniqueErrorCount());
}
1 change: 1 addition & 0 deletions compiler-rt/lib/rtsan/rtsan_stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
namespace __rtsan {

void IncrementTotalErrorCount();
void IncrementUniqueErrorCount();

void PrintStatisticsSummary();

Expand Down
39 changes: 39 additions & 0 deletions compiler-rt/test/rtsan/deduplicate_errors.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// RUN: %clangxx -fsanitize=realtime %s -o %t
// RUN: env RTSAN_OPTIONS="halt_on_error=false,print_stats_on_exit=true" %run %t 2>&1 | FileCheck %s

// UNSUPPORTED: ios

// Intent: Ensure all errors are deduplicated.

#include <unistd.h>

const int kNumViolations = 10;

void violation() [[clang::nonblocking]] {
for (int i = 0; i < kNumViolations; i++)
usleep(1);
}

void violation2() [[clang::nonblocking]] {
for (int i = 0; i < kNumViolations; i++)
violation();
}

void double_violation() [[clang::nonblocking]] {
violation();
violation2();
}

int main() {
violation(); // 1 unique errors here, but 10 total
violation2(); // 1 unique errors here, but 100 total
double_violation(); // 2 unique errors here, but 110 total
return 0;
}

// CHECK-COUNT-4: ==ERROR:
// CHECK-NOT: ==ERROR:

// CHECK: RealtimeSanitizer exit stats:
// CHECK-NEXT: Total error count: 220
// CHECK-NEXT: Unique error count: 4
1 change: 1 addition & 0 deletions compiler-rt/test/rtsan/exit_stats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ int main() {

// CHECK: RealtimeSanitizer exit stats:
// CHECK-NEXT: Total error count: 10
// CHECK-NEXT: Unique error count: 1