[[noreturn]] void terminate_handler() noexcept { // immediately unset this handler, to avoid endless recursions if // terminate() is accidentially triggered from here. std::set_terminate(old_terminate_handler); std::cout << "\n\x1b[31;1mFATAL: terminate has been called\x1b[m" << std::endl; if(std::exception_ptr e_ptr = std::current_exception()) { std::cout << "\n\x1b[33muncaught exception\x1b[m\n" << std::endl; try { std::rethrow_exception(e_ptr); } catch (Error &exc) { std::cout << exc << std::endl; } catch (std::exception &exc) { std::cout << "std::exception of type " << util::demangle(typeid(exc).name()) << ": " << exc.what() << std::endl; } catch (...) { std::cout << "non-standard exception object" << std::endl; } } std::cout << "\n\x1b[33mcurrent stack\x1b[m\n" << std::endl; StackAnalyzer backtrace; backtrace.analyze(); std::cout << backtrace << std::endl; // call the original handler, to enable debugger functionality, // and maybe print some additional useful info that we forgot about. std::cout << "\x1b[33mstandard terminate handler\x1b[m\n" << std::endl; std::terminate(); }
void StackAnalyzer::trim_to_current_stack_frame() { StackAnalyzer current; current.analyze(); while (not current.stack_addrs.empty() and not this->stack_addrs.empty()) { if (this->stack_addrs.back() != current.stack_addrs.back()) { break; } this->stack_addrs.pop_back(); current.stack_addrs.pop_back(); } }