diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 2b6041006..206a1a421 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -34,6 +34,10 @@ set(CMAKE_CXX_STANDARD 20) # Find the QtWidgets library find_package(Qt5Widgets CONFIG REQUIRED) +find_package(Backtrace REQUIRED) + +find_package(Boost REQUIRED COMPONENTS stacktrace_backtrace) + file(GLOB_RECURSE HDR_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.h") file(GLOB_RECURSE SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") if(MSVC) @@ -69,6 +73,9 @@ target_link_libraries(${PROJECT_NAME} Qt5::Widgets) target_link_libraries( ${PROJECT_NAME} + Boost::stacktrace_backtrace + Backtrace::Backtrace + ${CMAKE_DL_LIBS} # Required for dladdr() on Linux network dive_core device_mgr @@ -77,6 +84,17 @@ target_link_libraries( version_info ) +# Without this, it defaults to "Basic" (no line numbers) even if linked! +target_compile_definitions( + ${PROJECT_NAME} + PRIVATE + BOOST_STACKTRACE_USE_BACKTRACE +) + +if(UNIX AND NOT APPLE) + target_link_options(${PROJECT_NAME} PRIVATE -rdynamic) +endif() + # std::filesystem needs to link with libstdc++fs for g++ before 9.0 if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) target_link_libraries(${PROJECT_NAME} stdc++fs) diff --git a/ui/main.cpp b/ui/main.cpp index 661f4628b..d2e337016 100644 --- a/ui/main.cpp +++ b/ui/main.cpp @@ -27,6 +27,12 @@ #include "main_window.h" #include "utils/version_info.h" #include "custom_metatypes.h" + +// [NEW] Boost Stacktrace Includes +#include +#include +#include // Ensure iostream is included for std::cerr + #ifdef __linux__ # include #endif @@ -84,9 +90,23 @@ void setDarkMode(QApplication &app) QApplication::setPalette(darkPalette); } +void crash_handler(int signum) +{ + ::signal(signum, SIG_DFL); // Reset signal handler to default to avoid infinite loops + std::cerr << "\n\n[CRASH] Signal " << signum << " received.\n"; + std::cerr << "Stacktrace:\n"; + std::cerr << boost::stacktrace::stacktrace(); + std::cerr << std::endl; + std::raise(signum); // Re-raise the signal to let the OS handle the termination +} + //-------------------------------------------------------------------------------------------------- int main(int argc, char *argv[]) { + // Registering for Segmentation Fault (SIGSEGV) and Abort (SIGABRT) + ::signal(SIGSEGV, &crash_handler); + ::signal(SIGABRT, &crash_handler); + // Check number of arguments bool exit_after_load = false; if (argc > 1 && strcmp(argv[1], "--exit-after-load") == 0) diff --git a/ui/trace_window.cpp b/ui/trace_window.cpp index a2d06107f..d56fd70fb 100644 --- a/ui/trace_window.cpp +++ b/ui/trace_window.cpp @@ -746,6 +746,11 @@ void TraceWorker::run() const std::string host = "127.0.0.1"; int port = device->Port(); auto status = client.Connect(host, port); + + // intentional error + int *x = nullptr; + *x = 0; + if (!status.ok()) { std::string err_msg(status.message());