Improve terminate handler behavior when there's no active exception and also try to print a trace for non-cpptrace terminates

This commit is contained in:
Jeremy 2023-10-08 14:55:21 -04:00
parent f6f64954de
commit ae484f0ed2
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
2 changed files with 28 additions and 9 deletions

View File

@ -114,7 +114,8 @@ namespace cpptrace {
inline const_iterator cbegin() const noexcept { return frames.cbegin(); }
inline const_iterator cend() const noexcept { return frames.cend(); }
private:
CPPTRACE_API void print(std::ostream& stream, bool color, bool newline_at_end) const;
CPPTRACE_API void print(std::ostream& stream, bool color, bool newline_at_end, const char* header) const;
friend void print_terminate_trace();
};
CPPTRACE_API raw_trace generate_raw_trace(std::uint_least32_t skip = 0);

View File

@ -160,15 +160,15 @@ namespace cpptrace {
CPPTRACE_API
void stacktrace::print(std::ostream& stream, bool color) const {
print(stream, color, true);
print(stream, color, true, nullptr);
}
CPPTRACE_API
void stacktrace::print(std::ostream& stream, bool color, bool newline_at_end) const {
void stacktrace::print(std::ostream& stream, bool color, bool newline_at_end, const char* header) const {
if(color) {
detail::enable_virtual_terminal_processing_if_needed();
}
stream<<"Stack trace (most recent call first):"<<std::endl;
stream<<(header ? header : "Stack trace (most recent call first):")<<std::endl;
std::size_t counter = 0;
if(frames.empty()) {
stream<<"<empty trace>"<<std::endl;
@ -237,7 +237,7 @@ namespace cpptrace {
CPPTRACE_API
std::string stacktrace::to_string(bool color) const {
std::ostringstream oss;
print(oss, color, false);
print(oss, color, false, nullptr);
return std::move(oss).str();
}
@ -329,27 +329,45 @@ namespace cpptrace {
CPPTRACE_API extern const int stdout_fileno = detail::fileno(stdout);
CPPTRACE_API extern const int stderr_fileno = detail::fileno(stderr);
CPPTRACE_FORCE_NO_INLINE void print_terminate_trace() {
generate_trace(1).print(
std::cerr,
isatty(stderr_fileno),
true,
"Stack trace to reach terminate handler (most recent call first):"
);
}
[[noreturn]] CPPTRACE_API void terminate_handler() {
try {
std::rethrow_exception(std::current_exception());
auto ptr = std::current_exception();
if(ptr == nullptr) {
std::cerr << "terminate called without an active exception\n";
print_terminate_trace();
} else {
std::rethrow_exception(ptr);
}
} catch(cpptrace::exception& e) {
std::cerr << "Terminate called after throwing an instance of "
<< cpptrace::demangle(typeid(e).name())
<< demangle(typeid(e).name())
<< ": "
<< e.get_raw_what()
<< '\n';
e.get_trace().print(std::cerr, cpptrace::isatty(cpptrace::stderr_fileno));
e.get_trace().print(std::cerr, isatty(stderr_fileno));
} catch(std::exception& e) {
std::cerr << "Terminate called after throwing an instance of "
<< cpptrace::demangle(typeid(e).name())
<< demangle(typeid(e).name())
<< ": "
<< e.what()
<< '\n';
print_terminate_trace();
} catch(...) {
std::cerr << "Terminate called after throwing an instance of "
<< detail::exception_type_name()
<< "\n";
print_terminate_trace();
}
std::flush(std::cerr);
abort();
}