@@ -8,15 +8,46 @@ namespace cpptrace {
8
8
CPPTRACE_EXPORT const stacktrace& from_current_exception ();
9
9
10
10
namespace detail {
11
+ // Trace switch is to prevent multiple tracing of stacks on call stacks with multiple catches that don't
12
+ // immediately match
13
+ inline bool & get_trace_switch () {
14
+ static bool trace_switch = true ;
15
+ return trace_switch;
16
+ }
17
+
18
+ class CPPTRACE_EXPORT try_canary {
19
+ public:
20
+ ~try_canary () {
21
+ // Fires when we exit a try block, either via normal means or during unwinding.
22
+ // Either way: Flip the switch.
23
+ get_trace_switch () = true ;
24
+ }
25
+ };
26
+
27
+ CPPTRACE_EXPORT CPPTRACE_FORCE_NO_INLINE void collect_current_trace (std::size_t skip);
28
+
29
+ // this function can be void, however, a char return is used to prevent TCO of the collect_current_trace
30
+ CPPTRACE_FORCE_NO_INLINE inline char exception_unwind_interceptor (std::size_t skip) {
31
+ if (get_trace_switch ()) {
32
+ // Done during a search phase. Flip the switch off, no more traces until an unwind happens
33
+ get_trace_switch () = false ;
34
+ collect_current_trace (skip + 1 );
35
+ }
36
+ return 42 ;
37
+ }
38
+
11
39
#ifdef _MSC_VER
12
- CPPTRACE_EXPORT CPPTRACE_FORCE_NO_INLINE int exception_filter ();
40
+ CPPTRACE_FORCE_NO_INLINE inline int exception_filter () {
41
+ exception_unwind_interceptor (1 );
42
+ return 0 ; // EXCEPTION_CONTINUE_SEARCH
43
+ }
13
44
#else
14
45
class CPPTRACE_EXPORT unwind_interceptor {
15
46
public:
16
47
virtual ~unwind_interceptor ();
17
48
};
18
49
19
- CPPTRACE_EXPORT void do_prepare_unwind_interceptor ();
50
+ CPPTRACE_EXPORT void do_prepare_unwind_interceptor (char (*)(std:: size_t ) );
20
51
21
52
#ifndef CPPTRACE_DONT_PREPARE_UNWIND_INTERCEPTOR_ON
22
53
__attribute__ ((constructor)) inline void prepare_unwind_interceptor() {
@@ -27,7 +58,7 @@ namespace cpptrace {
27
58
// against it here too as a fast path, not that this should matter for performance
28
59
static bool did_prepare = false ;
29
60
if (!did_prepare) {
30
- do_prepare_unwind_interceptor ();
61
+ do_prepare_unwind_interceptor (exception_unwind_interceptor );
31
62
did_prepare = true ;
32
63
}
33
64
}
@@ -41,6 +72,7 @@ namespace cpptrace {
41
72
// exception handling (try/catch) in the same function."
42
73
#define CPPTRACE_TRY \
43
74
try { \
75
+ ::cpptrace::detail::try_canary cpptrace_try_canary; \
44
76
[&]() { \
45
77
__try { \
46
78
[&]() {
@@ -52,6 +84,10 @@ namespace cpptrace {
52
84
#else
53
85
#define CPPTRACE_TRY \
54
86
try { \
87
+ _Pragma (" GCC diagnostic push" ) \
88
+ _Pragma (" GCC diagnostic ignored \" -Wshadow\" " ) \
89
+ ::cpptrace::detail::try_canary cpptrace_try_canary; \
90
+ _Pragma (" GCC diagnostic pop" ) \
55
91
try {
56
92
#define CPPTRACE_CATCH (param ) \
57
93
} catch (::cpptrace::detail::unwind_interceptor&) {} \
0 commit comments