From 0fbdbf7ac05fccbaab891438f228d452cff003ac Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 15 May 2026 11:02:45 +0200 Subject: [PATCH 1/3] panic(): Include the panic message in the Sentry crash report --- src/libutil/error.cc | 2 ++ src/nix/crash.cc | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/libutil/error.cc b/src/libutil/error.cc index 8d6a1d9d9f5b..ebcbbb550585 100644 --- a/src/libutil/error.cc +++ b/src/libutil/error.cc @@ -6,6 +6,7 @@ #include "nix/util/signals.hh" #include "nix/util/terminal.hh" #include "nix/util/position.hh" +#include "nix/util/sentry.hh" #include #include @@ -452,6 +453,7 @@ void panic(std::string_view msg) writeErr("\n\n" ANSI_RED "terminating due to unexpected unrecoverable internal error: " ANSI_NORMAL); writeErr(msg); writeErr("\n"); + setSentryTag("panic_msg", msg.data()); std::terminate(); } diff --git a/src/nix/crash.cc b/src/nix/crash.cc index 3ed491ce75e4..aefdb85e5538 100644 --- a/src/nix/crash.cc +++ b/src/nix/crash.cc @@ -41,6 +41,11 @@ struct CmdCrash : Command std::bitset<4>{"012"}; } + else if (type == "panic") { + printError("Triggering a panic..."); + panic("test panic"); + } + else { throw Error("unknown crash type '%s'", type); } From 77ebf8f10a05a1e23e6067f5c49241a597026b02 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 15 May 2026 11:22:13 +0200 Subject: [PATCH 2/3] Include uncaught exception info to Sentry crash reports --- src/nix/crash.cc | 19 +++++++++++++++++++ src/nix/main.cc | 28 ++++++++++++++++++++++++++++ tests/functional/sentry.sh | 2 +- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/nix/crash.cc b/src/nix/crash.cc index aefdb85e5538..6778d70894ab 100644 --- a/src/nix/crash.cc +++ b/src/nix/crash.cc @@ -4,6 +4,11 @@ using namespace nix; +static void doThrow() +{ + throw Error("exception in destructor"); +} + struct CmdCrash : Command { std::string type; @@ -46,6 +51,20 @@ struct CmdCrash : Command panic("test panic"); } + else if (type == "terminate") { + printError("Triggering an std::terminate..."); + + struct Foo + { + ~Foo() + { + doThrow(); + } + }; + + Foo foo; + } + else { throw Error("unknown crash type '%s'", type); } diff --git a/src/nix/main.cc b/src/nix/main.cc index 4758ca1082fc..7d7dbb44ac5b 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -384,6 +384,33 @@ struct CmdHelpStores : Command static auto rCmdHelpStores = registerCommand("help-stores"); +static void terminateHandler() +{ + // Add the exception type and message to the Sentry crash report. + auto ex = std::current_exception(); + if (ex) { + try { + std::rethrow_exception(ex); + } catch (BaseError & e) { + try { + nix::setSentryTag("terminate_exception_type", typeid(e).name()); + nix::setSentryTag("terminate_exception_msg", e.message().c_str()); + } catch (...) { + } + } catch (const std::exception & e) { + try { + nix::setSentryTag("terminate_exception_type", typeid(e).name()); + nix::setSentryTag("terminate_exception_msg", e.what()); + } catch (...) { + } + } + } + + // Call the original terminate handler. + std::set_terminate(nullptr); + std::terminate(); +} + void mainWrapped(int argc, char ** argv) { savedArgv = argv; @@ -423,6 +450,7 @@ void mainWrapped(int argc, char ** argv) sentry_init(options); setSentryTag = [](const char * key, const char * value) { sentry_set_tag(key, value); }; setSentryTag("nix_command", argc > 0 ? std::string(baseNameOf(argv[0])).c_str() : ""); + std::set_terminate(terminateHandler); sentryEnabled = true; } diff --git a/tests/functional/sentry.sh b/tests/functional/sentry.sh index 0be7a3d305a4..b739f1ff3ad6 100644 --- a/tests/functional/sentry.sh +++ b/tests/functional/sentry.sh @@ -27,7 +27,7 @@ waitForCrashDump() { return 1 } -for type in segfault assert logic-error; do +for type in segfault assert logic-error panic terminate; do if [[ $type = logic-error && $(uname) = Darwin ]]; then continue; fi rm -rf "$sentryDir" From 83df16de22d269eb332f24368202cb00936a8d6f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 15 May 2026 11:29:55 +0200 Subject: [PATCH 3/3] Ensure null-termination --- src/libutil/error.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/error.cc b/src/libutil/error.cc index ebcbbb550585..758e734a3bb8 100644 --- a/src/libutil/error.cc +++ b/src/libutil/error.cc @@ -453,7 +453,7 @@ void panic(std::string_view msg) writeErr("\n\n" ANSI_RED "terminating due to unexpected unrecoverable internal error: " ANSI_NORMAL); writeErr(msg); writeErr("\n"); - setSentryTag("panic_msg", msg.data()); + setSentryTag("panic_msg", std::string(msg).c_str()); std::terminate(); }