aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libmain/crash-handler.cc41
-rw-r--r--src/libmain/crash-handler.hh21
-rw-r--r--src/libmain/meson.build2
-rw-r--r--src/libmain/shared.cc14
-rw-r--r--src/libmain/shared.hh2
-rw-r--r--src/libstore/globals.cc2
6 files changed, 76 insertions, 6 deletions
diff --git a/src/libmain/crash-handler.cc b/src/libmain/crash-handler.cc
new file mode 100644
index 000000000..3f1b9f7d8
--- /dev/null
+++ b/src/libmain/crash-handler.cc
@@ -0,0 +1,41 @@
+#include "crash-handler.hh"
+#include "fmt.hh"
+
+#include <boost/core/demangle.hpp>
+#include <exception>
+
+namespace nix {
+
+namespace {
+void onTerminate()
+{
+ std::cerr << "Lix crashed. This is a bug. We would appreciate if you report it along with what caused it at https://git.lix.systems/lix-project/lix/issues with the following information included:\n\n";
+ try {
+ std::exception_ptr eptr = std::current_exception();
+ if (eptr) {
+ std::rethrow_exception(eptr);
+ } else {
+ std::cerr << "std::terminate() called without exception\n";
+ }
+ } catch (const std::exception & ex) {
+ std::cerr << "Exception: " << boost::core::demangle(typeid(ex).name()) << ": " << ex.what() << "\n";
+ } catch (...) {
+ std::cerr << "Unknown exception! Spooky.\n";
+ }
+
+ std::cerr << "Stack trace:\n";
+ nix::printStackTrace();
+
+ std::abort();
+}
+}
+
+void registerCrashHandler()
+{
+ // DO NOT use this for signals. Boost stacktrace is very much not
+ // async-signal-safe, and in a world with ASLR, addr2line is pointless.
+ //
+ // If you want signals, set up a minidump system and do it out-of-process.
+ std::set_terminate(onTerminate);
+}
+}
diff --git a/src/libmain/crash-handler.hh b/src/libmain/crash-handler.hh
new file mode 100644
index 000000000..4c5641b8c
--- /dev/null
+++ b/src/libmain/crash-handler.hh
@@ -0,0 +1,21 @@
+#pragma once
+/// @file Crash handler for Lix that prints back traces (hopefully in instances where it is not just going to crash the process itself).
+/*
+ * Author's note: This will probably be partially/fully supplanted by a
+ * minidump writer like the following once we get our act together on crashes a
+ * little bit more:
+ * https://github.com/rust-minidump/minidump-writer
+ * https://github.com/EmbarkStudios/crash-handling
+ * (out of process implementation *should* be able to be done on-demand)
+ *
+ * Such an out-of-process implementation could then both make minidumps and
+ * print stack traces for arbitrarily messed-up process states such that we can
+ * safely give out backtraces for SIGSEGV and other deadly signals.
+ */
+
+namespace nix {
+
+/** Registers the Lix crash handler for std::terminate (currently; will support more crashes later). See also detectStackOverflow(). */
+void registerCrashHandler();
+
+}
diff --git a/src/libmain/meson.build b/src/libmain/meson.build
index a7cce287c..a1a888c16 100644
--- a/src/libmain/meson.build
+++ b/src/libmain/meson.build
@@ -1,5 +1,6 @@
libmain_sources = files(
'common-args.cc',
+ 'crash-handler.cc',
'loggers.cc',
'progress-bar.cc',
'shared.cc',
@@ -8,6 +9,7 @@ libmain_sources = files(
libmain_headers = files(
'common-args.hh',
+ 'crash-handler.hh',
'loggers.hh',
'progress-bar.hh',
'shared.hh',
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index bc9548e09..64bd00606 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -1,3 +1,4 @@
+#include "crash-handler.hh"
#include "globals.hh"
#include "shared.hh"
#include "store-api.hh"
@@ -118,6 +119,8 @@ static void sigHandler(int signo) { }
void initNix()
{
+ registerCrashHandler();
+
/* Turn on buffering for cerr. */
static char buf[1024];
std::cerr.rdbuf()->pubsetbuf(buf, sizeof(buf));
@@ -335,12 +338,15 @@ int handleExceptions(const std::string & programName, std::function<void()> fun)
} catch (BaseError & e) {
logError(e.info());
return e.info().status;
- } catch (std::bad_alloc & e) {
+ } catch (const std::bad_alloc & e) {
printError(error + "out of memory");
return 1;
- } catch (std::exception & e) {
- printError(error + e.what());
- return 1;
+ } catch (const std::exception & e) {
+ // Random exceptions bubbling into main are cause for bug reports, crash
+ std::terminate();
+ } catch (...) {
+ // Explicitly do not tolerate non-std exceptions escaping.
+ std::terminate();
}
return 0;
diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh
index b41efe567..49b72a54e 100644
--- a/src/libmain/shared.hh
+++ b/src/libmain/shared.hh
@@ -111,7 +111,7 @@ struct PrintFreed
/**
- * Install a SIGSEGV handler to detect stack overflows.
+ * Install a SIGSEGV handler to detect stack overflows. See also registerCrashHandler().
*/
void detectStackOverflow();
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index ffc2543ef..f43b759d2 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -443,7 +443,7 @@ static bool initLibStoreDone = false;
void assertLibStoreInitialized() {
if (!initLibStoreDone) {
printError("The program must call nix::initNix() before calling any libstore library functions.");
- abort();
+ std::terminate();
};
}