diff --git a/backward.hpp b/backward.hpp index 670aa45..6876474 100644 --- a/backward.hpp +++ b/backward.hpp @@ -92,6 +92,7 @@ #include #include #include +#include #if defined(BACKWARD_SYSTEM_LINUX) @@ -4164,6 +4165,18 @@ class Printer { class SignalHandling { public: + using PrinterPtr = std::shared_ptr; + + // Replace the default printer with a custom one. + // The supplied printer is stored and used by all signal handling output. + void set_printer(PrinterPtr printer) { + if (printer) { + printer_ = std::move(printer); + } + } + + PrinterPtr get_printer() const { return printer_; } + static std::vector make_default_signals() { const int posix_signals[] = { // Signals for which the default action is "Core". @@ -4188,7 +4201,14 @@ class SignalHandling { } SignalHandling(const std::vector &posix_signals = make_default_signals()) - : _loaded(false) { + : _loaded(false), printer_(std::make_shared()) { + // Default printer configuration (can be overwritten via set_printer()). + printer_->snippet = false; + printer_->address = false; + printer_->object = false; + printer_->inliner_context_size = 0; + printer_->trace_context_size = 0; + instance() = this; bool success = true; const size_t stack_size = 1024 * 1024 * 8; @@ -4229,6 +4249,12 @@ class SignalHandling { _loaded = success; } + ~SignalHandling() { + if (instance() == this) { + instance() = nullptr; + } + } + bool loaded() const { return _loaded; } static void handleSignal(int, siginfo_t *info, void *_ctx) { @@ -4272,9 +4298,8 @@ class SignalHandling { st.load_here(32, reinterpret_cast(uctx), info->si_addr); } - Printer printer; - printer.address = true; - printer.print(st, stderr); + // Use the configured printer. + instance()->printer_->print(st, stderr); #if (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700) || \ (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L) @@ -4285,8 +4310,14 @@ class SignalHandling { } private: + static SignalHandling *&instance() { + static SignalHandling *inst = nullptr; + return inst; + } + details::handle _stack_content; bool _loaded; + PrinterPtr printer_; #ifdef __GNUC__ __attribute__((noreturn)) @@ -4310,8 +4341,18 @@ class SignalHandling { class SignalHandling { public: + using PrinterPtr = std::shared_ptr; + + void set_printer(PrinterPtr printer) { + if (printer) { + printer_ = std::move(printer); + } + } + + PrinterPtr get_printer() const { return printer_; } + SignalHandling(const std::vector & = std::vector()) - : reporter_thread_([]() { + : printer_(std::make_shared()), reporter_thread_([]() { /* We handle crashes in a utility thread: backward structures and some Windows functions called here need stack space, which we do not have when we encounter a @@ -4333,6 +4374,9 @@ class SignalHandling { } cv().notify_one(); }) { + // Default printer configuration (can be overwritten via set_printer()). + printer_->address = true; + instance() = this; SetUnhandledExceptionFilter(crash_handler); signal(SIGABRT, signal_handler); @@ -4348,6 +4392,9 @@ class SignalHandling { bool loaded() const { return true; } ~SignalHandling() { + if (instance() == this) { + instance() = nullptr; + } { std::unique_lock lk(mtx()); crashed() = crash_status::normal_exit; @@ -4359,6 +4406,10 @@ class SignalHandling { } private: + static SignalHandling *&instance() { + static SignalHandling *inst = nullptr; + return inst; + } static CONTEXT *ctx() { static CONTEXT data; return &data; @@ -4465,7 +4516,8 @@ class SignalHandling { // macros. // StackTrace also requires that the PDBs are already loaded, which is done // in the constructor of TraceResolver - Printer printer; + auto *inst = instance(); + auto &printer = *inst->printer_; StackTrace st; st.set_machine_type(printer.resolver().machine_type()); @@ -4473,9 +4525,10 @@ class SignalHandling { st.load_here(32 + skip_frames, ctx()); st.skip_n_firsts(skip_frames); - printer.address = true; printer.print(st, std::cerr); } + + PrinterPtr printer_; }; #endif // BACKWARD_SYSTEM_WINDOWS @@ -4485,6 +4538,9 @@ class SignalHandling { class SignalHandling { public: SignalHandling(const std::vector & = std::vector()) {} + using PrinterPtr = std::shared_ptr; + void set_printer(PrinterPtr) {} + PrinterPtr get_printer() const { return PrinterPtr{}; } bool init() { return false; } bool loaded() { return false; } };