core: Collect and print stacktrace after fatal error

This commit is contained in:
Gabriel Ferreira
2025-04-30 17:22:32 +02:00
parent eda1ddd699
commit de7b73692b
2 changed files with 73 additions and 0 deletions

View File

@@ -3,3 +3,58 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Author: Gabriel Ferreira <gabrielcarvfer@gmail.com>
include(CheckCXXSourceCompiles)
# Some compilers (e.g. GCC <= 15) do not link std::stacktrace by default. If the
# sample program can be linked, it means it is indeed linked by default.
# Otherwise, we link it manually.
# https://en.cppreference.com/w/cpp/header/stacktrace
set(CMAKE_REQUIRED_FLAGS -std=c++23)
check_cxx_source_compiles(
"
#if __has_include(<stacktrace>)
int main()
{
return 0;
}
#endif
"
STACKTRACE_LIBRARY_ENABLED
)
if(STACKTRACE_LIBRARY_ENABLED)
set(stacktrace_flags)
if(GCC)
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0.0")
# GCC does not support stacktracing
elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14.0.0")
set(stacktrace_flags -lstdc++_libbacktrace)
else()
set(stacktrace_flags -lstdc++exp)
endif()
elseif(CLANG)
set(stacktrace_flags -lstdc++_libbacktrace)
else()
# Most likely MSVC, which does not need custom flags for this
endif()
set(CMAKE_REQUIRED_LIBRARIES ${stacktrace_flags})
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
check_cxx_source_compiles(
"
#include <iostream>
#include <stacktrace>
int main()
{
std::cout << std::stacktrace::current() << std::endl;
return 0;
}
"
STACKTRACE_LIBRARY_IS_LINKED
)
if(STACKTRACE_LIBRARY_IS_LINKED)
add_definitions(-DSTACKTRACE_LIBRARY_IS_LINKED=1)
link_libraries(${stacktrace_flags})
endif()
endif()

View File

@@ -17,6 +17,23 @@
#include <iostream>
#include <string_view>
// If stacktrace is available, print it on fatal errors
#ifdef STACKTRACE_LIBRARY_IS_LINKED
#include <stacktrace>
/**
* @brief Macro prints the current stack trace to standard error.
*
* This macro is defined only if the stacktrace library is linked.
*/
#define PRINT_STACKTRACE std::cerr << std::stacktrace::current() << std::endl
#else
/**
* @brief Macro does nothing if stacktrace library is not available.
*/
#define PRINT_STACKTRACE
#endif
/**
* @file
* @ingroup fatal
@@ -84,6 +101,7 @@ constexpr std::string_view NS_FATAL_MSG{"NS_FATAL, terminating"};
if (fatal) \
{ \
std::cerr << ns3::NS_FATAL_MSG << std::endl; \
PRINT_STACKTRACE; \
std::terminate(); \
} \
} while (false)