diff --git a/backward.hpp b/backward.hpp index 263cd1b..f28a1ac 100644 --- a/backward.hpp +++ b/backward.hpp @@ -336,6 +336,10 @@ #include #include +#ifdef BACKWARD_ATLEAST_CXX11 +#include +#endif + #include #ifdef _WIN64 @@ -4393,6 +4397,18 @@ class SignalHandling { } private: +#ifdef BACKWARD_ATLEAST_CXX11 + // Re-entrancy guard: ensure we only handle a crash once. + static std::atomic &handling_in_progress() { + static std::atomic flag{false}; + return flag; + } + + static bool begin_handling_once() { + bool expected = false; + return handling_in_progress().compare_exchange_strong(expected, true, std::memory_order_acq_rel); + } +#endif static CONTEXT *ctx() { static CONTEXT data; return &data; @@ -4442,11 +4458,21 @@ class SignalHandling { } static inline void terminator() { +#ifdef BACKWARD_ATLEAST_CXX11 + if (!begin_handling_once()) { + return; + } +#endif crash_handler(signal_skip_recs); abort(); } static inline void signal_handler(int) { +#ifdef BACKWARD_ATLEAST_CXX11 + if (!begin_handling_once()) { + return; + } +#endif crash_handler(signal_skip_recs); abort(); } @@ -4456,11 +4482,22 @@ class SignalHandling { const wchar_t *, unsigned int, uintptr_t) { +#ifdef BACKWARD_ATLEAST_CXX11 + if (!begin_handling_once()) { + return; + } +#endif crash_handler(signal_skip_recs); abort(); } NOINLINE static LONG WINAPI crash_handler(EXCEPTION_POINTERS *info) { +#ifdef BACKWARD_ATLEAST_CXX11 + // Only the first crash should be processed. + if (!begin_handling_once()) { + return EXCEPTION_CONTINUE_SEARCH; + } +#endif // The exception info supplies a trace from exactly where the issue was, // no need to skip records crash_handler(0, info->ContextRecord);