Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 63 additions & 7 deletions backward.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
#include <vector>
#include <exception>
#include <iterator>
#include <memory>

#if defined(BACKWARD_SYSTEM_LINUX)

Expand Down Expand Up @@ -4164,6 +4165,18 @@ class Printer {

class SignalHandling {
public:
using PrinterPtr = std::shared_ptr<Printer>;

// 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<int> make_default_signals() {
const int posix_signals[] = {
// Signals for which the default action is "Core".
Expand All @@ -4188,7 +4201,14 @@ class SignalHandling {
}

SignalHandling(const std::vector<int> &posix_signals = make_default_signals())
: _loaded(false) {
: _loaded(false), printer_(std::make_shared<Printer>()) {
// 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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -4272,9 +4298,8 @@ class SignalHandling {
st.load_here(32, reinterpret_cast<void *>(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)
Expand All @@ -4285,8 +4310,14 @@ class SignalHandling {
}

private:
static SignalHandling *&instance() {
static SignalHandling *inst = nullptr;
return inst;
}

details::handle<char *> _stack_content;
bool _loaded;
PrinterPtr printer_;

#ifdef __GNUC__
__attribute__((noreturn))
Expand All @@ -4310,8 +4341,18 @@ class SignalHandling {

class SignalHandling {
public:
using PrinterPtr = std::shared_ptr<Printer>;

void set_printer(PrinterPtr printer) {
if (printer) {
printer_ = std::move(printer);
}
}

PrinterPtr get_printer() const { return printer_; }

SignalHandling(const std::vector<int> & = std::vector<int>())
: reporter_thread_([]() {
: printer_(std::make_shared<Printer>()), 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
Expand All @@ -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);
Expand All @@ -4348,6 +4392,9 @@ class SignalHandling {
bool loaded() const { return true; }

~SignalHandling() {
if (instance() == this) {
instance() = nullptr;
}
{
std::unique_lock<std::mutex> lk(mtx());
crashed() = crash_status::normal_exit;
Expand All @@ -4359,6 +4406,10 @@ class SignalHandling {
}

private:
static SignalHandling *&instance() {
static SignalHandling *inst = nullptr;
return inst;
}
static CONTEXT *ctx() {
static CONTEXT data;
return &data;
Expand Down Expand Up @@ -4465,17 +4516,19 @@ 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());
st.set_thread_handle(thread_handle());
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
Expand All @@ -4485,6 +4538,9 @@ class SignalHandling {
class SignalHandling {
public:
SignalHandling(const std::vector<int> & = std::vector<int>()) {}
using PrinterPtr = std::shared_ptr<Printer>;
void set_printer(PrinterPtr) {}
PrinterPtr get_printer() const { return PrinterPtr{}; }
bool init() { return false; }
bool loaded() { return false; }
};
Expand Down