|
18 | 18 | #include "sanitizer_common/sanitizer_atomic.h" |
19 | 19 | #include "sanitizer_common/sanitizer_common.h" |
20 | 20 | #include "sanitizer_common/sanitizer_mutex.h" |
| 21 | +#include "sanitizer_common/sanitizer_stackdepot.h" |
21 | 22 | #include "sanitizer_common/sanitizer_stacktrace.h" |
22 | 23 |
|
23 | 24 | using namespace __rtsan; |
@@ -49,7 +50,30 @@ static auto OnViolationAction(DiagnosticsInfo info) { |
49 | 50 | return [info]() { |
50 | 51 | IncrementTotalErrorCount(); |
51 | 52 |
|
52 | | - PrintDiagnostics(info); |
| 53 | + BufferedStackTrace stack; |
| 54 | + |
| 55 | + // We use the unwind_on_fatal flag here because of precedent with other |
| 56 | + // sanitizers, this action is not necessarily fatal if halt_on_error=false |
| 57 | + stack.Unwind(info.pc, info.bp, nullptr, |
| 58 | + common_flags()->fast_unwind_on_fatal); |
| 59 | + |
| 60 | + // If in the future we interop with other sanitizers, we will |
| 61 | + // need to make our own stackdepot |
| 62 | + StackDepotHandle handle = StackDepotPut_WithHandle(stack); |
| 63 | + |
| 64 | + const bool is_stack_novel = handle.use_count() == 0; |
| 65 | + |
| 66 | + // Marked UNLIKELY as if user is runing with halt_on_error=false |
| 67 | + // we expect a high number of duplicate stacks. We are willing |
| 68 | + // To pay for the first insertion. |
| 69 | + if (UNLIKELY(is_stack_novel)) { |
| 70 | + IncrementUniqueErrorCount(); |
| 71 | + |
| 72 | + PrintDiagnostics(info); |
| 73 | + stack.Print(); |
| 74 | + |
| 75 | + handle.inc_use_count_unsafe(); |
| 76 | + } |
53 | 77 |
|
54 | 78 | if (flags().halt_on_error) |
55 | 79 | Die(); |
|
0 commit comments