This introduces three new things: * `handleException` which prints out exception details and its stack trace. * `handleExceptionWithAsyncTrace` which does the same, but also prints the async trace if any. * `LIX_BLOCK_ON` which is awaits a promise and adds an exception trace if an exception got thrown, similar to `LIX_TRY_AWAIT`. However, this is not supposed to be used in async functions, but on callsites of `aio.blockOn()` which is especially useful for Hydra[1]. For `LIX_BLOCK_ON` I had to introduce another function because there's apparently no way to implement all of it in a macro: on macros with compound statements the return value must be a trivial expression at the bottom, i.e. no `try`/`catch`. Now, returning the value from the `try`-block requires the variable to be defined up-front, but for that we'd need to know the type-name. Hence the construction with a template-function being invoked by a macro that injects the current source-location. [1] https://git.lix.systems/lix-project/hydra/pulls/52 Change-Id: I56cc92c94f7e8f0be5d4dc5a7d8cb21a92e776ef
45 lines
1.3 KiB
C++
45 lines
1.3 KiB
C++
#include "lix/libmain/crash-handler.hh"
|
|
#include "lix/libutil/error.hh"
|
|
#include "lix/libutil/logging.hh"
|
|
|
|
#include <boost/core/demangle.hpp>
|
|
#include <exception>
|
|
|
|
namespace nix {
|
|
|
|
namespace {
|
|
|
|
void onTerminate()
|
|
{
|
|
std::shared_ptr<const std::list<BaseException::AsyncTraceFrame>> asyncTrace;
|
|
|
|
logFatal("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");
|
|
try {
|
|
std::exception_ptr eptr = std::current_exception();
|
|
if (eptr) {
|
|
std::rethrow_exception(eptr);
|
|
} else {
|
|
logFatal("std::terminate() called without exception");
|
|
}
|
|
} catch (const BaseException & ex) {
|
|
logException("Exception", ex);
|
|
} catch (const std::exception & ex) { // NOLINT(lix-foreign-exceptions)
|
|
logException("Exception", ex);
|
|
} catch (...) {
|
|
logFatal("Unknown exception! Spooky.");
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|