From 323dae6c7fd982f444e1736410888037239e662c Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Sat, 2 Sep 2017 13:41:26 -0600 Subject: Install a crash handler ..that prints a backtrace on crash. --- applications/kube/CMakeLists.txt | 1 + applications/kube/main.cpp | 106 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/applications/kube/CMakeLists.txt b/applications/kube/CMakeLists.txt index 2d0df2ad..2d4c9da7 100644 --- a/applications/kube/CMakeLists.txt +++ b/applications/kube/CMakeLists.txt @@ -21,6 +21,7 @@ target_link_libraries(${PROJECT_NAME} Qt5::Widgets Qt5::WebEngine KF5::Package + ${CMAKE_DL_LIBS} ) install(TARGETS ${PROJECT_NAME} DESTINATION ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/applications/kube/main.cpp b/applications/kube/main.cpp index 44897b2e..a6b51c38 100644 --- a/applications/kube/main.cpp +++ b/applications/kube/main.cpp @@ -17,6 +17,19 @@ 02110-1301, USA. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include @@ -28,6 +41,94 @@ #include +//Print a demangled stacktrace +void printStacktrace() +{ + int skip = 1; + void *callstack[128]; + const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]); + char buf[1024]; + int nFrames = backtrace(callstack, nMaxFrames); + char **symbols = backtrace_symbols(callstack, nFrames); + + std::ostringstream trace_buf; + for (int i = skip; i < nFrames; i++) { + // printf("%s\n", symbols[i]); + Dl_info info; + if (dladdr(callstack[i], &info) && info.dli_sname) { + char *demangled = NULL; + int status = -1; + if (info.dli_sname[0] == '_') { + demangled = abi::__cxa_demangle(info.dli_sname, NULL, 0, &status); + } + snprintf(buf, sizeof(buf), "%-3d %*p %s + %zd\n", + i, int(2 + sizeof(void*) * 2), callstack[i], + status == 0 ? demangled : + info.dli_sname == 0 ? symbols[i] : info.dli_sname, + (char *)callstack[i] - (char *)info.dli_saddr); + free(demangled); + } else { + snprintf(buf, sizeof(buf), "%-3d %*p %s\n", + i, int(2 + sizeof(void*) * 2), callstack[i], symbols[i]); + } + trace_buf << buf; + } + free(symbols); + if (nFrames == nMaxFrames) { + trace_buf << "[truncated]\n"; + } + std::cerr << trace_buf.str(); +} + +static int sCounter = 0; + +void crashHandler(int signal) +{ + //Guard against crashing in here + if (sCounter > 1) { + std::_Exit(EXIT_FAILURE); + } + sCounter++; + + if (signal == SIGABRT) { + std::cerr << "SIGABRT received\n"; + } else if (signal == SIGSEGV) { + std::cerr << "SIGSEV received\n"; + } else { + std::cerr << "Unexpected signal " << signal << " received\n"; + } + + printStacktrace(); + + std::fprintf(stdout, "Sleeping for 10s to attach a debugger: gdb attach %i\n", getpid()); + std::this_thread::sleep_for(std::chrono::seconds(10)); + + // std::system("exec gdb -p \"$PPID\" -ex \"thread apply all bt\""); + // This only works if we actually have xterm and X11 available + // std::system("exec xterm -e gdb -p \"$PPID\""); + + std::_Exit(EXIT_FAILURE); +} + +void terminateHandler() +{ + // std::exception_ptr exptr = std::current_exception(); + // if (exptr != 0) + // { + // // the only useful feature of std::exception_ptr is that it can be rethrown... + // try { + // std::rethrow_exception(exptr); + // } catch (std::exception &ex) { + // std::fprintf(stderr, "Terminated due to exception: %s\n", ex.what()); + // } catch (...) { + // std::fprintf(stderr, "Terminated due to unknown exception\n"); + // } + // } else { + std::fprintf(stderr, "Terminated due to unknown reason.\n"); + // } + std::abort(); +} + class KubeImageProvider : public QQuickImageProvider { public: @@ -68,6 +169,11 @@ public: int main(int argc, char *argv[]) { + + std::signal(SIGSEGV, crashHandler); + std::signal(SIGABRT, crashHandler); + std::set_terminate(terminateHandler); + QApplication app(argc, argv); app.setFont(QFont{"Noto Sans", app.font().pointSize(), QFont::Normal}); -- cgit v1.2.3