From bb29d27d54b6b4dadb519e941759f61485e33f39 Mon Sep 17 00:00:00 2001 From: Stella Smith Date: Sun, 11 Feb 2024 18:20:05 -0300 Subject: [PATCH] make stacktrace on terminate more detailed --- CMakeLists.txt | 7 +++- conanfile.py | 1 + include/engine/sdl/Error.hpp | 17 ++++++--- src/engine/rendering/opengl/Renderer.cpp | 1 + src/main.cpp | 46 ++++++++++++++++-------- 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 67957f6..110512a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ find_package(EnTT CONFIG REQUIRED) find_package(SDL2 CONFIG REQUIRED) find_package(Boost CONFIG REQUIRED) find_package(SDL2_image CONFIG REQUIRED) +find_package(range-v3 CONFIG REQUIRED) add_subdirectory(external) @@ -127,7 +128,11 @@ target_include_directories(little_game PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/inclu target_link_libraries(little_game PRIVATE SDL2::SDL2 glm::glm imgui_impl_sdl2 rapidjson SDL2_image::SDL2_image - fmt::fmt spdlog::spdlog EnTT::EnTT Boost::boost) + fmt::fmt spdlog::spdlog EnTT::EnTT Boost::boost range-v3::range-v3) + +if (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_link_libraries(little_game PRIVATE Boost::stacktrace_backtrace) +endif() set_target_properties(little_game PROPERTIES CXX_STANDARD 20 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS ON) target_compile_features(little_game PUBLIC cxx_std_20) diff --git a/conanfile.py b/conanfile.py index 9c055d9..3c27916 100644 --- a/conanfile.py +++ b/conanfile.py @@ -58,6 +58,7 @@ def requirements(self): self.requires("boost/[~1.83]") self.requires("sdl/[~2]", override=True) self.requires("sdl_image/[~2]") + self.requires("range-v3/[~0.12]") if self.options.with_opengl: self.requires("glad/[~0.1]") diff --git a/include/engine/sdl/Error.hpp b/include/engine/sdl/Error.hpp index 922bc91..45dc8ac 100644 --- a/include/engine/sdl/Error.hpp +++ b/include/engine/sdl/Error.hpp @@ -4,15 +4,22 @@ #include #include -#include +#include +#include +#include namespace engine::sdl { - class Error final : std::runtime_error { - public: - using std::runtime_error::runtime_error; + class Error final : public std::runtime_error { + private: + Error(char const *message) + : std::runtime_error(message) + { + } - [[nodiscard]] static Error current() + public: + [[nodiscard]] + static Error current() { return Error(SDL_GetError()); } diff --git a/src/engine/rendering/opengl/Renderer.cpp b/src/engine/rendering/opengl/Renderer.cpp index c50065f..235f4b1 100644 --- a/src/engine/rendering/opengl/Renderer.cpp +++ b/src/engine/rendering/opengl/Renderer.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include diff --git a/src/main.cpp b/src/main.cpp index f8c5c18..1302168 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,12 +3,15 @@ #include #include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -27,21 +30,6 @@ static void set_spdlog_sinks() sinks.push_back(std::make_shared(1024 * 5)); } -[[gnu::constructor]] -static void set_terminate_handler() -{ - static std::terminate_handler const default_handler = std::get_terminate(); - - auto handler = []() { - auto const stacktrace = boost::stacktrace::stacktrace(); - for (auto const &frame : stacktrace) - spdlog::critical("{}", fmt::streamed(frame)); // do not use the macro, location printed by it can be confused - - default_handler(); - }; - std::set_terminate(+handler); -} - static std::vector audio_drivers() { int const n = SDL_GetNumAudioDrivers(); @@ -64,8 +52,36 @@ static std::vector video_drivers() return result; } +static void terminate_handler() +{ + if (auto exception_ptr = std::current_exception()) { + try { + std::rethrow_exception(exception_ptr); + } catch (std::exception const &e) { + spdlog::critical("terminate called with an active exception"); + auto const type_name = boost::core::demangled_name(typeid(e)); + spdlog::critical("exception: type={:?}, what={:?}", type_name, e.what()); + } catch (...) { + // TODO: find a way to get this information on Windows + auto const type_name = boost::core::demangled_name(*abi::__cxa_current_exception_type()); + spdlog::critical("terminate called with an active exception"); + spdlog::critical("exception: type={:?}", type_name); + } + } else { + spdlog::critical("terminate called without an active exception"); + } + + auto const stacktrace = boost::stacktrace::stacktrace(); + spdlog::critical("stacktrace:"); + for (auto const &[i, frame] : stacktrace | ranges::view::reverse | ranges::view::enumerate) + spdlog::critical(" #{:02}: {}", i, fmt::streamed(frame)); + std::abort(); +} + int main(int argc, char **argv) { + std::set_terminate(+terminate_handler); + #ifdef SDL_MAIN_HANDLED SDL_SetMainReady(); #endif