1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-24 22:11:15 +02:00

port crash-handler from lix to nix

It was first introduced in 19e0ce2c03

In Nix we only register the crash handler in main instead of initNix,
because library user may want to use their own crash handler.

Sample output:

Mar 12 08:38:06 eve nix[2303762]: Nix crashed. This is a bug. Please report this at https://github.com/NixOS/nix/issues with the following information included:
Mar 12 08:38:06 eve nix[2303762]: Exception: nix::SysError: error: writing to file: Resource temporarily unavailable
Mar 12 08:38:06 eve nix[2303762]: Stack trace:
Mar 12 08:38:06 eve nix[2303762]:  0# 0x000000000076876A in nix
                                   1# 0x00007FDA40E9F20A in /nix/store/2lhklm5aizx30qbw49acnrrzkj9lbmij-gcc-14-20241116-lib/lib/libstdc++.so.6
                                   2# std::unexpected() in /nix/store/2lhklm5aizx30qbw49acnrrzkj9lbmij-gcc-14-20241116-lib/lib/libstdc++.so.6
                                   3# 0x00007FDA40E9F487 in /nix/store/2lhklm5aizx30qbw49acnrrzkj9lbmij-gcc-14-20241116-lib/lib/libstdc++.so.6
                                   4# nix::writeFull(int, std::basic_string_view<char, std::char_traits<char> >, bool) in /home/joerg/git/nix/inst/lib/libnixutil.so
                                   5# nix::writeLine(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) in /home/joerg/git/nix/inst/lib/libnixutil.so
                                   6# nix::JSONLogger::write(nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> const&) in /home/joerg/git/nix/inst/lib/libnixutil.so
                                   7# nix::JSONLogger::logEI(nix::ErrorInfo const&) in /home/joerg/git/nix/inst/lib/libnixutil.so
                                   8# nix::Logger::logEI(nix::Verbosity, nix::ErrorInfo) in nix
                                   9# nix::handleExceptions(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<void ()>) in /home/joerg/git/nix/inst/lib/libnixmain.so
                                  10# 0x000000000087A563 in nix
                                  11# 0x00007FDA40BD41FE in /nix/store/6q2mknq81cyscjmkv72fpcsvan56qhmg-glibc-2.40-66/lib/libc.so.6
                                  12# __libc_start_main in /nix/store/6q2mknq81cyscjmkv72fpcsvan56qhmg-glibc-2.40-66/lib/libc.so.6
                                  13# 0x00000000006F4DF5 in nix

Co-authored-by: eldritch horrors <pennae@lix.systems>
(cherry picked from commit 163f94412a)
This commit is contained in:
Jade Lovelace 2025-03-12 08:29:29 +00:00 committed by Mergify
parent 616109a040
commit b1f0f1c5a1
4 changed files with 82 additions and 0 deletions

67
src/nix/crash-handler.cc Normal file
View file

@ -0,0 +1,67 @@
#include "crash-handler.hh"
#include "fmt.hh"
#include "logging.hh"
#include <boost/core/demangle.hpp>
#include <exception>
#include <sstream>
// Darwin and FreeBSD stdenv do not define _GNU_SOURCE but do have _Unwind_Backtrace.
#if __APPLE__ || __FreeBSD__
# define BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED
#endif
#include <boost/stacktrace/stacktrace.hpp>
#ifndef _WIN32
# include <syslog.h>
#endif
namespace nix {
namespace {
void logFatal(std::string const & s)
{
writeToStderr(s + "\n");
// std::string for guaranteed null termination
#ifndef _WIN32
syslog(LOG_CRIT, "%s", s.c_str());
#endif
}
void onTerminate()
{
logFatal(
"Nix crashed. This is a bug. Please report this at https://github.com/NixOS/nix/issues with the following information included:\n");
try {
std::exception_ptr eptr = std::current_exception();
if (eptr) {
std::rethrow_exception(eptr);
} else {
logFatal("std::terminate() called without exception");
}
} catch (const std::exception & ex) {
logFatal(fmt("Exception: %s: %s", boost::core::demangle(typeid(ex).name()), ex.what()));
} catch (...) {
logFatal("Unknown exception!");
}
logFatal("Stack trace:");
std::stringstream ss;
ss << boost::stacktrace::stacktrace();
logFatal(ss.str());
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);
}
}

11
src/nix/crash-handler.hh Normal file
View file

@ -0,0 +1,11 @@
#pragma once
/// @file Crash handler for Nix that prints back traces (hopefully in instances where it is not just going to crash the
/// process itself).
namespace nix {
/** Registers the Nix crash handler for std::terminate (currently; will support more crashes later). See also
* detectStackOverflow(). */
void registerCrashHandler();
}

View file

@ -20,6 +20,7 @@
#include "flake/flake.hh"
#include "self-exe.hh"
#include "json-utils.hh"
#include "crash-handler.hh"
#include <sys/types.h>
#include <regex>
@ -354,6 +355,8 @@ void mainWrapped(int argc, char * * argv)
{
savedArgv = argv;
registerCrashHandler();
/* The chroot helper needs to be run before any threads have been
started. */
#ifndef _WIN32

View file

@ -77,6 +77,7 @@ nix_sources = [config_h] + files(
'config-check.cc',
'config.cc',
'copy.cc',
'crash-handler.cc',
'derivation-add.cc',
'derivation-show.cc',
'derivation.cc',