aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJade Lovelace <lix@jade.fyi>2024-08-24 21:11:30 -0700
committerJade Lovelace <lix@jade.fyi>2024-09-25 14:03:45 -0700
commit19e0ce2c03d8e0baa16998b086665664c420c1df (patch)
treee9aad862687b3546d4cc8e299cce40f6ef6b549a /tests
parent8a6b84df147f5f38bae710fac9ec085d9d4e8ded (diff)
main: log stack traces for std::terminate
These stack traces kind of suck for the reasons mentioned on the CppTrace page here (no symbols for inline functions is a major one): https://github.com/jeremy-rifkin/cpptrace I would consider using CppTrace if it were packaged, but to be honest, I think that the more reasonable option is actually to move entirely to out-of-process crash handling and symbolization. The reason for this is that if you want to generate anything of substance on SIGSEGV or really any deadly signal, you are stuck in async-signal-safe land, which is not a place to be trying to run a symbolizer. LLVM does it anyway, probably carefully, and chromium *can* do it on debug builds but in general uses crashpad: https://source.chromium.org/chromium/chromium/src/+/main:base/debug/stack_trace_posix.cc;l=974;drc=82dff63dbf9db05e9274e11d9128af7b9f51ceaa;bpv=1;bpt=1 However, some stack traces are better than *no* stack traces when we get mystery exceptions falling out the bottom of the program. I've also promoted the path for "mystery exceptions falling out the bottom of the program" to hard crash and generate a core dump because although there's been some months since the last one of these, these are nonetheless always *atrociously* diagnosed. We can't improve the crash handling further until either we use Crashpad (which involves more C++ deps, no thanks) or we put in the ostensibly work in progress Rust minidump infrastructure, in which case we need to finish full support for Rust in libutil first. Sample report: Lix crashed. This is a bug. We would appreciate if you report it at https://git.lix.systems/lix-project/lix/issues with the following information included: Exception: std::runtime_error: lol Stack trace: 0# nix::printStackTrace() in /home/jade/lix/lix3/build/src/nix/../libutil/liblixutil.so 1# 0x000073C9862331F2 in /home/jade/lix/lix3/build/src/nix/../libmain/liblixmain.so 2# 0x000073C985F2E21A in /nix/store/p44qan69linp3ii0xrviypsw2j4qdcp2-gcc-13.2.0-lib/lib/libstdc++.so.6 3# 0x000073C985F2E285 in /nix/store/p44qan69linp3ii0xrviypsw2j4qdcp2-gcc-13.2.0-lib/lib/libstdc++.so.6 4# nix::handleExceptions(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<void ()>) in /home/jade/lix/lix3/build/src/nix/../libmain/liblixmain.so 5# 0x00005CF65B6B048B in /home/jade/lix/lix3/build/src/nix/nix 6# 0x000073C985C8810E in /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6 7# __libc_start_main in /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6 8# 0x00005CF65B610335 in /home/jade/lix/lix3/build/src/nix/nix Change-Id: I1a9f6d349b617fd7145a37159b78ecb9382cb4e9
Diffstat (limited to 'tests')
-rw-r--r--tests/unit/libmain/crash.cc56
-rw-r--r--tests/unit/meson.build7
2 files changed, 62 insertions, 1 deletions
diff --git a/tests/unit/libmain/crash.cc b/tests/unit/libmain/crash.cc
new file mode 100644
index 000000000..883dc39bd
--- /dev/null
+++ b/tests/unit/libmain/crash.cc
@@ -0,0 +1,56 @@
+#include <gtest/gtest.h>
+#include "crash-handler.hh"
+
+namespace nix {
+
+class OopsException : public std::exception
+{
+ const char * msg;
+
+public:
+ OopsException(const char * msg) : msg(msg) {}
+ const char * what() const noexcept override
+ {
+ return msg;
+ }
+};
+
+void causeCrashForTesting(std::function<void()> fixture)
+{
+ registerCrashHandler();
+ std::cerr << "time to crash\n";
+ try {
+ fixture();
+ } catch (...) {
+ std::terminate();
+ }
+}
+
+TEST(CrashHandler, exceptionName)
+{
+ ASSERT_DEATH(
+ causeCrashForTesting([]() { throw OopsException{"lol oops"}; }),
+ "time to crash\nLix crashed.*OopsException: lol oops"
+ );
+}
+
+TEST(CrashHandler, unknownTerminate)
+{
+ ASSERT_DEATH(
+ causeCrashForTesting([]() { std::terminate(); }),
+ "time to crash\nLix crashed.*std::terminate\\(\\) called without exception"
+ );
+}
+
+TEST(CrashHandler, nonStdException)
+{
+ ASSERT_DEATH(
+ causeCrashForTesting([]() {
+ // NOLINTNEXTLINE(hicpp-exception-baseclass): intentional
+ throw 4;
+ }),
+ "time to crash\nLix crashed.*Unknown exception! Spooky\\."
+ );
+}
+
+}
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index 8ff0b5ec5..894f48b2a 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -262,9 +262,14 @@ test(
protocol : 'gtest',
)
+libmain_tests_sources = files(
+ 'libmain/crash.cc',
+ 'libmain/progress-bar.cc',
+)
+
libmain_tester = executable(
'liblixmain-tests',
- files('libmain/progress-bar.cc'),
+ libmain_tests_sources,
dependencies : [
liblixmain,
liblixexpr,