Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions src/libutil/error.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 <cinttypes>
#include <iostream>
Expand Down Expand Up @@ -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", std::string(msg).c_str());
std::terminate();
}

Expand Down
24 changes: 24 additions & 0 deletions src/nix/crash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

using namespace nix;

static void doThrow()
{
throw Error("exception in destructor");
}

struct CmdCrash : Command
{
std::string type;
Expand Down Expand Up @@ -41,6 +46,25 @@ struct CmdCrash : Command
std::bitset<4>{"012"};
}

else if (type == "panic") {
printError("Triggering a panic...");
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);
}
Expand Down
28 changes: 28 additions & 0 deletions src/nix/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,33 @@ struct CmdHelpStores : Command

static auto rCmdHelpStores = registerCommand<CmdHelpStores>("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;
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/functional/sentry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading