[compiler-rt] f5b95db - [rtsan] Only print out unique stack traces (#110028)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 26 10:53:41 PDT 2024
Author: Chris Apple
Date: 2024-09-26T10:53:37-07:00
New Revision: f5b95db4c3ea266489a68a7655425b18ce5805f6
URL: https://github.com/llvm/llvm-project/commit/f5b95db4c3ea266489a68a7655425b18ce5805f6
DIFF: https://github.com/llvm/llvm-project/commit/f5b95db4c3ea266489a68a7655425b18ce5805f6.diff
LOG: [rtsan] Only print out unique stack traces (#110028)
# Why?
In real-time programming, you often have a process or dispatch loop that
is called many, many, many times. Without de-duplication the user will
be drowning in errors.
Introduce a way to only print the stacks one time only, if they have
been seen before
Added:
compiler-rt/test/rtsan/deduplicate_errors.cpp
Modified:
compiler-rt/lib/rtsan/rtsan.cpp
compiler-rt/lib/rtsan/rtsan_diagnostics.cpp
compiler-rt/lib/rtsan/rtsan_stats.cpp
compiler-rt/lib/rtsan/rtsan_stats.h
compiler-rt/test/rtsan/exit_stats.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/rtsan/rtsan.cpp b/compiler-rt/lib/rtsan/rtsan.cpp
index 87c3611935ee5f..6fcff5e326a52f 100644
--- a/compiler-rt/lib/rtsan/rtsan.cpp
+++ b/compiler-rt/lib/rtsan/rtsan.cpp
@@ -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;
@@ -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();
diff --git a/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp b/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp
index f82001f5b2057c..cfe71481d3dc78 100644
--- a/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp
@@ -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 * {
@@ -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);
}
diff --git a/compiler-rt/lib/rtsan/rtsan_stats.cpp b/compiler-rt/lib/rtsan/rtsan_stats.cpp
index 7c1ccf2876f081..dac7b23c3ef520 100644
--- a/compiler-rt/lib/rtsan/rtsan_stats.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_stats.cpp
@@ -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());
}
diff --git a/compiler-rt/lib/rtsan/rtsan_stats.h b/compiler-rt/lib/rtsan/rtsan_stats.h
index 3aa30f6a5db76a..a72098792c89c9 100644
--- a/compiler-rt/lib/rtsan/rtsan_stats.h
+++ b/compiler-rt/lib/rtsan/rtsan_stats.h
@@ -15,6 +15,7 @@
namespace __rtsan {
void IncrementTotalErrorCount();
+void IncrementUniqueErrorCount();
void PrintStatisticsSummary();
diff --git a/compiler-rt/test/rtsan/deduplicate_errors.cpp b/compiler-rt/test/rtsan/deduplicate_errors.cpp
new file mode 100644
index 00000000000000..7d60d4d7da7dda
--- /dev/null
+++ b/compiler-rt/test/rtsan/deduplicate_errors.cpp
@@ -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
diff --git a/compiler-rt/test/rtsan/exit_stats.cpp b/compiler-rt/test/rtsan/exit_stats.cpp
index b46a0fd62bac1a..4341fbb0f9cf21 100644
--- a/compiler-rt/test/rtsan/exit_stats.cpp
+++ b/compiler-rt/test/rtsan/exit_stats.cpp
@@ -21,3 +21,4 @@ int main() {
// CHECK: RealtimeSanitizer exit stats:
// CHECK-NEXT: Total error count: 10
+// CHECK-NEXT: Unique error count: 1
More information about the llvm-commits
mailing list