86 lines
2.5 KiB
C++
86 lines
2.5 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2010-2019 Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#include "./system.hpp"
|
|
|
|
#include "./assert.hpp"
|
|
#include "./debugger.hpp"
|
|
#include "./except.hpp"
|
|
#include "./crash.hpp"
|
|
|
|
#include "../backtrace.hpp"
|
|
#include "../log.hpp"
|
|
|
|
#include <cstdlib>
|
|
#include <exception>
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
static std::terminate_handler old_handler = nullptr;
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
static void abort_with_trace (void)
|
|
{
|
|
// We used to trigger a breakpoint so that our debugger didn't just let the
|
|
// child terminate (ie, the behaviour of CLion/Win32/GDB).
|
|
//
|
|
// But this might silently terminate the program instead of allowing us the
|
|
// chance to dump a backtrace depending on the precise mechanism for
|
|
// `breakpoint`; in particular SIGTRAP and SIGINT trigger this.
|
|
#if 0
|
|
breakpoint ();
|
|
#endif
|
|
|
|
// If we're here because of an exception we may as well rethrow and hope
|
|
// that the system will print exception data during the abort process.
|
|
//
|
|
// But we can at least try to print anything derived from std::exception
|
|
// (which is a likely guess) before we self-destruct.
|
|
if (auto ptr = std::current_exception (); ptr) {
|
|
try {
|
|
std::rethrow_exception (ptr);
|
|
} catch (std::exception const &x) {
|
|
LOG_EMERGENCY ("unhandled exception: {}\n{}", x.what (), ::cruft::backtrace {});
|
|
} catch (cruft::error const &x) {
|
|
LOG_EMERGENCY ("unhandled exception: {}\n{}", x, ::cruft::backtrace {});
|
|
} catch (...) {
|
|
LOG_EMERGENCY ("unhandled exception\n{}", ::cruft::backtrace {});
|
|
}
|
|
} else {
|
|
LOG_EMERGENCY ("aborting: {}", ::cruft::backtrace {});
|
|
}
|
|
|
|
old_handler ();
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
cruft::debug::init (void)
|
|
{
|
|
init_crash_handler ();
|
|
|
|
old_handler = std::set_terminate (abort_with_trace);
|
|
CHECK_NEQ (
|
|
reinterpret_cast<void*> (old_handler),
|
|
reinterpret_cast<void*> (abort_with_trace)
|
|
);
|
|
|
|
if (!debug_enabled && !getenv ("DEBUG"))
|
|
return;
|
|
|
|
LOG_DEBUG ("setting debug environment");
|
|
enable_fpe ();
|
|
force_console ();
|
|
prepare_debugger ();
|
|
|
|
if (getenv ("DEBUG_WAIT"))
|
|
await_debugger ();
|
|
}
|