From 5881085e1e4fa84ed98f2d98a639cfaf630fe37f Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 28 Apr 2026 10:30:10 +0200 Subject: [PATCH 01/12] add cpptrace --- host-configs/tpls.cmake | 4 +++ src/CMakeLists.txt | 4 +++ src/cmake/GeosxConfig.cmake | 1 + .../thirdparty/SetupGeosxThirdParty.cmake | 36 +++++++++++++++++++ src/coreComponents/common/GeosxConfig.hpp.in | 3 ++ 5 files changed, 48 insertions(+) diff --git a/host-configs/tpls.cmake b/host-configs/tpls.cmake index 1a4ab1701e6..ded9597c5be 100644 --- a/host-configs/tpls.cmake +++ b/host-configs/tpls.cmake @@ -109,3 +109,7 @@ endif() if(EXISTS ${GEOS_TPL_DIR}/mathpresso) set(MATHPRESSO_DIR ${GEOS_TPL_DIR}/mathpresso CACHE PATH "" FORCE) endif() + +if(EXISTS ${GEOS_TPL_DIR}/cpptrace) + set(CPPTRACE_DIR ${GEOS_TPL_DIR}/cpptrace CACHE PATH "" FORCE) +endif() \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 36dc61610ac..49f662b4c91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -133,6 +133,10 @@ if( ENABLE_HIP ) list( APPEND extraComponentsLinkList blt::hip ) endif() +if( ENABLE_CPPTRACE ) + list( APPEND extraComponentsLinkList cpptrace::cpptrace ) +endif() + blt_add_executable( NAME geosx SOURCES main/main.cpp DEPENDS_ON geosx_core diff --git a/src/cmake/GeosxConfig.cmake b/src/cmake/GeosxConfig.cmake index 39c206418f8..c79c1e07a8b 100644 --- a/src/cmake/GeosxConfig.cmake +++ b/src/cmake/GeosxConfig.cmake @@ -1,5 +1,6 @@ set( PREPROCESSOR_DEFINES BOUNDS_CHECK CALIPER + CPPTRACE CHAI CUDA CUDA_NVTOOLSEXT diff --git a/src/cmake/thirdparty/SetupGeosxThirdParty.cmake b/src/cmake/thirdparty/SetupGeosxThirdParty.cmake index 2bb024b2b05..b400c51f3d8 100644 --- a/src/cmake/thirdparty/SetupGeosxThirdParty.cmake +++ b/src/cmake/thirdparty/SetupGeosxThirdParty.cmake @@ -897,6 +897,7 @@ else() set(ENABLE_PETSC OFF CACHE BOOL "" FORCE) message(STATUS "Not using PETSc") endif() + ################################ # VTK ################################ @@ -935,6 +936,41 @@ else() message(STATUS "Not using VTK") endif() +################################ +# CPPTRACE +################################ +if( DEFINED CPPTRACE_DIR ) + message( STATUS "CPPTRACE_DIR = ${CPPTRACE_DIR}" ) + + if( DEFINED ZSTD_DIR ) + message( STATUS "ZSTD_DIR = ${ZSTD_DIR}" ) + list( PREPEND CMAKE_PREFIX_PATH "${ZSTD_DIR}" ) + endif() + if( DEFINED LIBDWARF_DIR ) + message( STATUS "LIBDWARF_DIR = ${LIBDWARF_DIR}" ) + list( PREPEND CMAKE_PREFIX_PATH "${LIBDWARF_DIR}" ) + endif() + + find_package( cpptrace REQUIRED + PATHS ${CPPTRACE_DIR} + NO_DEFAULT_PATH ) + + if( DEFINED cpptrace_VERSION ) + message( " ----> cpptrace_VERSION=${cpptrace_VERSION}") + endif() + + blt_convert_to_system_includes( TARGET cpptrace::cpptrace ) + + set( ENABLE_CPPTRACE ON CACHE BOOL "" ) + set( thirdPartyLibs ${thirdPartyLibs} cpptrace::cpptrace ) +else() + if( ENABLE_CPPTRACE ) + message( WARNING "ENABLE_CPPTRACE is ON but CPPTRACE_DIR isn't defined." ) + endif() + + set( ENABLE_CPPTRACE OFF CACHE BOOL "" ) + message( STATUS "Not using cpptrace" ) +endif() ################################ # uncrustify diff --git a/src/coreComponents/common/GeosxConfig.hpp.in b/src/coreComponents/common/GeosxConfig.hpp.in index 0c8ee16237f..aec6965c34b 100644 --- a/src/coreComponents/common/GeosxConfig.hpp.in +++ b/src/coreComponents/common/GeosxConfig.hpp.in @@ -38,6 +38,9 @@ /// Enables use of CHAI (CMake option ENABLE_CHAI) #cmakedefine GEOS_USE_CHAI +/// Enables use of Cpptrace (CMake option ENABLE_CPPTRACE) +#cmakedefine GEOS_USE_CPPTRACE + /// Enables use of Mathpresso library (CMake option ENABLE_MATHPRESSO) #cmakedefine GEOS_USE_MATHPRESSO From 6a684f27202ba3c6afbc4dc5a422f9fe398a8d92 Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 28 Apr 2026 10:31:31 +0200 Subject: [PATCH 02/12] modify main to use cpptrace stacktrace --- .../common/logger/ErrorHandling.cpp | 13 ++- src/main/main.cpp | 85 +++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/coreComponents/common/logger/ErrorHandling.cpp b/src/coreComponents/common/logger/ErrorHandling.cpp index 6881e11259a..3b36f7edf37 100644 --- a/src/coreComponents/common/logger/ErrorHandling.cpp +++ b/src/coreComponents/common/logger/ErrorHandling.cpp @@ -203,20 +203,25 @@ DiagnosticMsgBuilder & DiagnosticMsgBuilder::addRank( integer const rank ) DiagnosticMsgBuilder & DiagnosticMsgBuilder::addCallStackInfo( std::string_view ossStackTrace ) { + m_errorMsg.m_sourceCallStack.clear(); + m_errorMsg.m_isValidStackTrace = false; + std::string str = std::string( ossStackTrace ); std::istringstream iss( str ); std::string stackLine; std::size_t index; - std::regex pattern( R"(Frame \d+: \S+)" ); + std::regex lvArrayPattern( R"(Frame \d+: \S+)" ); + std::regex cpptracePattern( R"(^\s*#\d+\s+)" ); while( std::getline( iss, stackLine ) ) { - if( std::regex_search( stackLine, pattern )) + std::smatch m; + if( std::regex_search( stackLine, m, lvArrayPattern ) || + std::regex_search( stackLine, m, cpptracePattern ) ) { m_errorMsg.m_isValidStackTrace = true; - index = stackLine.find( ':' ); - m_errorMsg.m_sourceCallStack.push_back( stackLine.substr( index + 1 ) ); + m_errorMsg.m_sourceCallStack.push_back( stackLine.substr( m.position() + m.length() ) ); } } diff --git a/src/main/main.cpp b/src/main/main.cpp index 00c7a560ef6..d347d17e48e 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -16,6 +16,7 @@ // Source includes #include "common/logger/ErrorHandling.hpp" #include "common/logger/Logger.hpp" +#include "common/GeosxConfig.hpp" #include "common/MemoryInfos.hpp" #include "common/TimingMacros.hpp" #include "common/Units.hpp" @@ -23,6 +24,9 @@ #include "mainInterface/ProblemManager.hpp" #include "mainInterface/GeosxState.hpp" #include "mainInterface/version.hpp" +#ifdef GEOS_USE_CPPTRACE +#include "" +#endif using namespace geos; @@ -30,6 +34,51 @@ using namespace geos; int main( int argc, char *argv[] ) { +#ifdef GEOS_USE_CPPTRACE + cpptrace::try_catch + ( + [&] + { + std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now(); + + std::unique_ptr< CommandLineOptions > commandLineOptions = basicSetup( argc, argv, true ); + + outputVersionInfo(); + + GEOS_LOG_RANK_0( GEOS_FMT( "Started at {:%Y-%m-%d %H:%M:%S}", startTime ) ); + + std::chrono::system_clock::duration initTime; + std::chrono::system_clock::duration runTime; + { + GeosxState state( std::move( commandLineOptions ) ); + + bool const problemToRun = state.initializeDataRepository(); + if( problemToRun ) + { + state.applyInitialConditions(); + state.run(); + GEOS_WARNING_IF( state.getState() != State::COMPLETED, "Simulation exited early." ); + } + + initTime = state.getInitTime(); + runTime = state.getRunTime(); + } + + MemoryLogging::getInstance().memoryStatsReport(); + + basicCleanup( false ); + + std::chrono::system_clock::time_point endTime = std::chrono::system_clock::now(); + std::chrono::system_clock::duration totalTime = endTime - startTime; + + GEOS_LOG_RANK_0( GEOS_FMT( "Finished at {:%Y-%m-%d %H:%M:%S}", endTime ) ); + GEOS_LOG_RANK_0( GEOS_FMT( "total time {}", units::TimeFormatInfo::fromDuration( totalTime ) ) ); + GEOS_LOG_RANK_0( GEOS_FMT( "initialization time {}", units::TimeFormatInfo::fromDuration( initTime ) ) ); + GEOS_LOG_RANK_0( GEOS_FMT( "run time {}", units::TimeFormatInfo::fromDuration( runTime ) ) ); + + // don't return with cpptrace (Windows limitation) + }, +#else try { std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now(); @@ -71,18 +120,52 @@ int main( int argc, char *argv[] ) return 0; } +#endif + +#ifdef GEOS_USE_CPPTRACE + // A NotAnError is thrown if "-h" or "--help" option is used. + [&]( NotAnError const & ) + { + basicCleanup( false ); + }, +#else // A NotAnError is thrown if "-h" or "--help" option is used. catch( NotAnError const & ) { basicCleanup( false ); return 0; } +#endif + +#ifdef GEOS_USE_CPPTRACE + [&]( geos::Exception & e ) + { // GEOS generated exceptions management + ErrorLogger::global().flushCurrentExceptionMessage(); + basicCleanup( true ); + LvArray::system::callErrorHandler(); + }, +#else catch( geos::Exception & e ) { // GEOS generated exceptions management ErrorLogger::global().flushCurrentExceptionMessage(); basicCleanup( true ); LvArray::system::callErrorHandler(); } +#endif + +#ifdef GEOS_USE_CPPTRACE + [&]( std::exception const & e ) + { // native exceptions management + cpptrace::stacktrace const trace = cpptrace::from_current_exception(); + ErrorLogger::global().flushErrorMsg( ErrorLogger::global().initCurrentExceptionMessage( + MsgType::Exception, e.what(), + ::geos::logger::internal::g_rank ) + .addCallStackInfo( trace.to_string() ) + .getDiagnosticMsg()); + basicCleanup( true ); + LvArray::system::callErrorHandler(); + }, +#else catch( std::exception const & e ) { // native exceptions management ErrorLogger::global().flushErrorMsg( ErrorLogger::global().initCurrentExceptionMessage( @@ -93,5 +176,7 @@ int main( int argc, char *argv[] ) basicCleanup( true ); LvArray::system::callErrorHandler(); } +#endif + return 0; } From 69ba20e114a1694637ec54d700738126f9aecc1f Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 28 Apr 2026 14:43:03 +0200 Subject: [PATCH 03/12] fix typo in include --- src/main/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/main.cpp b/src/main/main.cpp index d347d17e48e..4bee88b340b 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -25,7 +25,7 @@ #include "mainInterface/GeosxState.hpp" #include "mainInterface/version.hpp" #ifdef GEOS_USE_CPPTRACE -#include "" +#include #endif From 39051faf88dc886d61fd6624f10e1746f4a2e4fd Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 28 Apr 2026 14:43:19 +0200 Subject: [PATCH 04/12] add missing parenthesis --- src/main/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/main.cpp b/src/main/main.cpp index 4bee88b340b..082eaf7218b 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -164,7 +164,7 @@ int main( int argc, char *argv[] ) .getDiagnosticMsg()); basicCleanup( true ); LvArray::system::callErrorHandler(); - }, + } ); #else catch( std::exception const & e ) { // native exceptions management From 8abfda8430972f45aa93b8e863dd5d6f88c655ce Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 28 Apr 2026 15:45:49 +0200 Subject: [PATCH 05/12] reorganize main.cpp for readability --- src/main/main.cpp | 116 +++++++++++++--------------------------------- 1 file changed, 31 insertions(+), 85 deletions(-) diff --git a/src/main/main.cpp b/src/main/main.cpp index 082eaf7218b..be58645cb58 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -34,52 +34,7 @@ using namespace geos; int main( int argc, char *argv[] ) { -#ifdef GEOS_USE_CPPTRACE - cpptrace::try_catch - ( - [&] - { - std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now(); - - std::unique_ptr< CommandLineOptions > commandLineOptions = basicSetup( argc, argv, true ); - - outputVersionInfo(); - - GEOS_LOG_RANK_0( GEOS_FMT( "Started at {:%Y-%m-%d %H:%M:%S}", startTime ) ); - - std::chrono::system_clock::duration initTime; - std::chrono::system_clock::duration runTime; - { - GeosxState state( std::move( commandLineOptions ) ); - - bool const problemToRun = state.initializeDataRepository(); - if( problemToRun ) - { - state.applyInitialConditions(); - state.run(); - GEOS_WARNING_IF( state.getState() != State::COMPLETED, "Simulation exited early." ); - } - - initTime = state.getInitTime(); - runTime = state.getRunTime(); - } - - MemoryLogging::getInstance().memoryStatsReport(); - - basicCleanup( false ); - - std::chrono::system_clock::time_point endTime = std::chrono::system_clock::now(); - std::chrono::system_clock::duration totalTime = endTime - startTime; - - GEOS_LOG_RANK_0( GEOS_FMT( "Finished at {:%Y-%m-%d %H:%M:%S}", endTime ) ); - GEOS_LOG_RANK_0( GEOS_FMT( "total time {}", units::TimeFormatInfo::fromDuration( totalTime ) ) ); - GEOS_LOG_RANK_0( GEOS_FMT( "initialization time {}", units::TimeFormatInfo::fromDuration( initTime ) ) ); - GEOS_LOG_RANK_0( GEOS_FMT( "run time {}", units::TimeFormatInfo::fromDuration( runTime ) ) ); - - // don't return with cpptrace (Windows limitation) - }, -#else - try + auto runMain = [&] { std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now(); @@ -117,64 +72,55 @@ int main( int argc, char *argv[] ) GEOS_LOG_RANK_0( GEOS_FMT( "total time {}", units::TimeFormatInfo::fromDuration( totalTime ) ) ); GEOS_LOG_RANK_0( GEOS_FMT( "initialization time {}", units::TimeFormatInfo::fromDuration( initTime ) ) ); GEOS_LOG_RANK_0( GEOS_FMT( "run time {}", units::TimeFormatInfo::fromDuration( runTime ) ) ); + }; - return 0; - } -#endif - -#ifdef GEOS_USE_CPPTRACE // A NotAnError is thrown if "-h" or "--help" option is used. - [&]( NotAnError const & ) + auto onNotAnError = [&]( NotAnError const & ) { basicCleanup( false ); - }, -#else - // A NotAnError is thrown if "-h" or "--help" option is used. - catch( NotAnError const & ) - { - basicCleanup( false ); - return 0; - } -#endif + }; -#ifdef GEOS_USE_CPPTRACE - [&]( geos::Exception & e ) + auto onGeosException = [&]( geos::Exception & e ) { // GEOS generated exceptions management ErrorLogger::global().flushCurrentExceptionMessage(); basicCleanup( true ); LvArray::system::callErrorHandler(); - }, -#else - catch( geos::Exception & e ) - { // GEOS generated exceptions management - ErrorLogger::global().flushCurrentExceptionMessage(); - basicCleanup( true ); - LvArray::system::callErrorHandler(); - } -#endif + }; -#ifdef GEOS_USE_CPPTRACE - [&]( std::exception const & e ) + auto onStdException = [&]( std::exception const & e ) { // native exceptions management - cpptrace::stacktrace const trace = cpptrace::from_current_exception(); +#ifdef GEOS_USE_CPPTRACE + std::string const stacktrace = cpptrace::from_current_exception().to_string(); +#else + std::string const stacktrace = LvArray::system::stackTrace( true ); +#endif ErrorLogger::global().flushErrorMsg( ErrorLogger::global().initCurrentExceptionMessage( MsgType::Exception, e.what(), ::geos::logger::internal::g_rank ) - .addCallStackInfo( trace.to_string() ) + .addCallStackInfo( stacktrace ) .getDiagnosticMsg()); basicCleanup( true ); LvArray::system::callErrorHandler(); - } ); + }; + +#ifdef GEOS_USE_CPPTRACE + cpptrace::try_catch( runMain, onNotAnError, onGeosException, onStdException ); #else + try + { + runMain(); + } + catch( NotAnError const & e ) + { + onNotAnError( e ); + } + catch( geos::Exception & e ) + { + onGeosException( e ); + } catch( std::exception const & e ) - { // native exceptions management - ErrorLogger::global().flushErrorMsg( ErrorLogger::global().initCurrentExceptionMessage( - MsgType::Exception, e.what(), - ::geos::logger::internal::g_rank ) - .addCallStackInfo( LvArray::system::stackTrace( true ) ) - .getDiagnosticMsg()); - basicCleanup( true ); - LvArray::system::callErrorHandler(); + { + onStdException( e ); } #endif From a02d8632bb69d507572daccddfbb521f48f1d0eb Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 5 May 2026 16:41:16 +0200 Subject: [PATCH 06/12] use cpptrace for GeosException --- src/coreComponents/common/CMakeLists.txt | 6 ++ .../common/initializeEnvironment.cpp | 5 +- .../common/logger/ErrorHandling.cpp | 6 +- src/coreComponents/common/logger/Logger.hpp | 7 +- .../common/logger/StackTrace.cpp | 86 +++++++++++++++++++ .../common/logger/StackTrace.hpp | 67 +++++++++++++++ src/main/main.cpp | 12 ++- 7 files changed, 181 insertions(+), 8 deletions(-) create mode 100644 src/coreComponents/common/logger/StackTrace.cpp create mode 100644 src/coreComponents/common/logger/StackTrace.hpp diff --git a/src/coreComponents/common/CMakeLists.txt b/src/coreComponents/common/CMakeLists.txt index d0143b9564b..9dbfd6081f1 100644 --- a/src/coreComponents/common/CMakeLists.txt +++ b/src/coreComponents/common/CMakeLists.txt @@ -43,6 +43,7 @@ set( common_headers logger/Logger.hpp logger/ErrorHandling.hpp logger/ExternalErrorHandler.hpp + logger/StackTrace.hpp MpiWrapper.hpp Path.hpp Span.hpp @@ -82,6 +83,7 @@ set( common_sources logger/Logger.cpp logger/ErrorHandling.cpp logger/ExternalErrorHandler.cpp + logger/StackTrace.cpp BufferAllocator.cpp MemoryInfos.cpp MpiWrapper.cpp @@ -136,6 +138,10 @@ if( ENABLE_CALIPER ) endif() endif() +if( ENABLE_CPPTRACE ) + list( APPEND dependencyList cpptrace::cpptrace ) +endif() + blt_add_library( NAME common SOURCES ${common_sources} HEADERS ${common_headers} diff --git a/src/coreComponents/common/initializeEnvironment.cpp b/src/coreComponents/common/initializeEnvironment.cpp index e43263c8528..90f00b5a731 100644 --- a/src/coreComponents/common/initializeEnvironment.cpp +++ b/src/coreComponents/common/initializeEnvironment.cpp @@ -26,6 +26,7 @@ #include #include #include +#include "logger/StackTrace.hpp" #include "umpire/util/MemoryResourceTraits.hpp" #include "umpire/util/Platform.hpp" @@ -86,7 +87,7 @@ void setupLogger() } else { - std::string const stackHistory = LvArray::system::stackTrace( true ); + std::string const stackHistory = StackTrace::stackTrace(); DiagnosticMsg diagnosticMsg; ErrorLogger::global().flushErrorMsg( DiagnosticMsgBuilder::init( diagnosticMsg, MsgType::Error, errorMsg, @@ -109,7 +110,7 @@ void setupLogger() ExternalErrorHandler::instance().flush( "before signal error output" ); // error message output - std::string const stackHistory = LvArray::system::stackTrace( true ); + std::string const stackHistory = StackTrace::stackTrace(); DiagnosticMsg diagnosticMsg; ErrorLogger::global().flushErrorMsg( DiagnosticMsgBuilder::init( diagnosticMsg, MsgType::ExternalError, "", diff --git a/src/coreComponents/common/logger/ErrorHandling.cpp b/src/coreComponents/common/logger/ErrorHandling.cpp index 3b36f7edf37..7eefeb74f3c 100644 --- a/src/coreComponents/common/logger/ErrorHandling.cpp +++ b/src/coreComponents/common/logger/ErrorHandling.cpp @@ -18,8 +18,11 @@ */ #include "ErrorHandling.hpp" +#include "Logger.hpp" +#include "StackTrace.hpp" #include "common/DataTypes.hpp" #include "common/logger/Logger.hpp" +#include "common/logger/StackTrace.hpp" #include "common/format/StringUtilities.hpp" #include @@ -66,7 +69,7 @@ DiagnosticMsgBuilder ErrorLogger::initCurrentExceptionMessage( MsgType msgType, m_getCurrentExceptionMsg = DiagnosticMsgBuilder::init( diagnosticMsg, msgType, msgContent, rank ) - .addCallStackInfo( LvArray::system::stackTrace( true ) ) + .addCallStackInfo( StackTrace::stackTrace() ) .getDiagnosticMsg(); return DiagnosticMsgBuilder::modify( m_getCurrentExceptionMsg ); } @@ -209,7 +212,6 @@ DiagnosticMsgBuilder & DiagnosticMsgBuilder::addCallStackInfo( std::string_view std::string str = std::string( ossStackTrace ); std::istringstream iss( str ); std::string stackLine; - std::size_t index; std::regex lvArrayPattern( R"(Frame \d+: \S+)" ); std::regex cpptracePattern( R"(^\s*#\d+\s+)" ); diff --git a/src/coreComponents/common/logger/Logger.hpp b/src/coreComponents/common/logger/Logger.hpp index b23ba87a39d..f692ff96b3a 100644 --- a/src/coreComponents/common/logger/Logger.hpp +++ b/src/coreComponents/common/logger/Logger.hpp @@ -23,6 +23,7 @@ // Source includes #include "LvArray/src/Macros.hpp" #include "common/logger/GeosExceptions.hpp" +#include "common/logger/StackTrace.hpp" // System includes #include @@ -161,7 +162,7 @@ ::geos::logger::internal::g_rank ) \ .setCodeLocation( __FILE__, __LINE__ ) \ .setCause( __causemsgsoss.str() ) \ - .addCallStackInfo( LvArray::system::stackTrace( true ) ) \ + .addCallStackInfo( StackTrace::stackTrace() ) \ .addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ )); \ GEOS_GLOBAL_LOGGER.flushCurrentExceptionMessage(); \ LvArray::system::callErrorHandler(); \ @@ -248,7 +249,7 @@ ::geos::logger::internal::g_rank ) \ .setCodeLocation( __FILE__, __LINE__ ) \ .setCause( __causemsgsoss.str() ) \ - .addCallStackInfo( LvArray::system::stackTrace( true ) ) \ + .addCallStackInfo( StackTrace::stackTrace() ) \ .addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ )) \ .getDiagnosticMsg(); \ auto ex = GEOS_DETAIL_FIRST_ARG( __VA_ARGS__ )(); \ @@ -341,7 +342,7 @@ ::geos::logger::internal::g_rank ) \ .setCodeLocation( __FILE__, __LINE__ ) \ .setCause( __causemsgsoss.str() ) \ - .addCallStackInfo( LvArray::system::stackTrace( true ) ) \ + .addCallStackInfo( StackTrace::stackTrace() ) \ .addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ )) \ .getDiagnosticMsg() ); \ } \ diff --git a/src/coreComponents/common/logger/StackTrace.cpp b/src/coreComponents/common/logger/StackTrace.cpp new file mode 100644 index 00000000000..c94a483f310 --- /dev/null +++ b/src/coreComponents/common/logger/StackTrace.cpp @@ -0,0 +1,86 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file StackTrace.cpp + */ + +#include "StackTrace.hpp" +#include "LvArray/src/system.hpp" + +#include "common/GeosxConfig.hpp" +#ifdef GEOS_USE_CPPTRACE +#include +#include +#include +#endif + +namespace geos +{ + + +std::string StackTrace::stackTrace() +{ +#ifdef GEOS_USE_CPPTRACE + return formatter().format( cpptrace::generate_trace( /* skip = */ 1 ) ); +#else + return LvArray::system::stackTrace( true ); +#endif +} + +#ifdef GEOS_USE_CPPTRACE +cpptrace::formatter & StackTrace::formatter() +{ + static cpptrace::formatter fmt = cpptrace::formatter{} + .header( "" ) + .addresses( cpptrace::formatter::address_mode::none ) + .paths( cpptrace::formatter::path_mode::basename ) + .symbols( cpptrace::formatter::symbol_mode::pretty ) + .snippets( false ) + .columns( true ) + .filtered_frame_placeholders( false ) + .filter( []( cpptrace::stacktrace_frame const & frame ) + { + static char const * const blacklist[] = { + "__cxa_throw", + "__cxa_rethrow", + "_Unwind_RaiseException", + "_Unwind_Resume", + "cpptrace::detail::", + "cpptrace::v1::detail::", + "cpptrace::try_catch::", + "cpptrace::v1::try_catch::", + }; + for( char const * symbolToHide : blacklist ) + { + if( frame.symbol.find( symbolToHide ) != std::string::npos ) + { + return false; + } + } + return true; + } ); + + return fmt; +} + +std::string StackTrace::formatStackTrace( cpptrace::v1::stacktrace stacktrace ) +{ + return formatter().format( stacktrace ); +} +#endif + + +} /* namespace geos */ diff --git a/src/coreComponents/common/logger/StackTrace.hpp b/src/coreComponents/common/logger/StackTrace.hpp new file mode 100644 index 00000000000..91e01d3869f --- /dev/null +++ b/src/coreComponents/common/logger/StackTrace.hpp @@ -0,0 +1,67 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file StackTrace.hpp + */ + +#ifndef GEOS_COMMON_LOGGER_STACKTRACE_HPP +#define GEOS_COMMON_LOGGER_STACKTRACE_HPP + +#include "common/GeosxConfig.hpp" // For the following guards +#ifdef GEOS_USE_CPPTRACE +#include +#include +#endif + +#include + +namespace geos +{ + +/** + * @brief Utility class to interact with stack traces. + */ +class StackTrace +{ +public: + + /** + * @brief Get a stack trace for the current thread. + * @return The stack trace as a string. + */ + static std::string stackTrace(); + +#ifdef GEOS_USE_CPPTRACE + /** + * @brief Access the configured cpptrace formatter. + * @return The formatter instance. + */ + static cpptrace::formatter & formatter(); + + /** + * @brief Format a cpptrace stacktrace using the configured formatter. + * @param stacktrace The cpptrace stack trace to format. + * @return Formatted stack trace string. + */ + static std::string formatStackTrace( cpptrace::v1::stacktrace stacktrace ); +#endif + +}; + + +} /* namespace geos */ + +#endif /* GEOS_COMMON_LOGGER_STACKTRACE_HPP */ diff --git a/src/main/main.cpp b/src/main/main.cpp index be58645cb58..75e633b252f 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -16,6 +16,7 @@ // Source includes #include "common/logger/ErrorHandling.hpp" #include "common/logger/Logger.hpp" +#include "common/logger/StackTrace.hpp" #include "common/GeosxConfig.hpp" #include "common/MemoryInfos.hpp" #include "common/TimingMacros.hpp" @@ -82,6 +83,15 @@ int main( int argc, char *argv[] ) auto onGeosException = [&]( geos::Exception & e ) { // GEOS generated exceptions management +#ifdef GEOS_USE_CPPTRACE + std::string const stacktrace = StackTrace::formatStackTrace( cpptrace::from_current_exception() ); +#else + std::string const stacktrace = LvArray::system::stackTrace( true ); +#endif + if( !stacktrace.empty() ) + { + ErrorLogger::global().modifyCurrentExceptionMessage().addCallStackInfo( stacktrace ); + } ErrorLogger::global().flushCurrentExceptionMessage(); basicCleanup( true ); LvArray::system::callErrorHandler(); @@ -90,7 +100,7 @@ int main( int argc, char *argv[] ) auto onStdException = [&]( std::exception const & e ) { // native exceptions management #ifdef GEOS_USE_CPPTRACE - std::string const stacktrace = cpptrace::from_current_exception().to_string(); + std::string const stacktrace = StackTrace::formatStackTrace( cpptrace::from_current_exception() ); #else std::string const stacktrace = LvArray::system::stackTrace( true ); #endif From 2977086104b262e6b4d368974cdbf1e63c6642ea Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 5 May 2026 17:07:27 +0200 Subject: [PATCH 07/12] add cpptrace in buildGuide --- src/docs/sphinx/buildGuide/BuildProcess.rst | 1 + src/docs/sphinx/buildGuide/Dependencies.rst | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/docs/sphinx/buildGuide/BuildProcess.rst b/src/docs/sphinx/buildGuide/BuildProcess.rst index cd3910c451c..25ab8af4a4d 100644 --- a/src/docs/sphinx/buildGuide/BuildProcess.rst +++ b/src/docs/sphinx/buildGuide/BuildProcess.rst @@ -70,6 +70,7 @@ Option Default Explanation ``ENABLE_CUDA_NVTOOLSEXT`` ``OFF`` Enable CUDA NVTX user instrumentation (via GEOS_MARK_SCOPE or GEOS_MARK_FUNCTION macros) ``ENABLE_HIP`` ``OFF`` Build with HIP/ROCM (also applies to TPLs) ``ENABLE_DOCS`` ``ON`` Build documentation (Sphinx and Doxygen) +``ENABLE_CPPTRACE`` ``ON`` Enable cpptrace stack traces ``ENABLE_WARNINGS_AS_ERRORS`` ``ON`` Treat all warnings as errors ``ENABLE_PVTPackage`` ``ON`` Enable PVTPackage library (required for compositional flow runs) ``ENABLE_TOTALVIEW_OUTPUT`` ``OFF`` Enables TotalView debugger custom view of GEOS data structures diff --git a/src/docs/sphinx/buildGuide/Dependencies.rst b/src/docs/sphinx/buildGuide/Dependencies.rst index 03824bb29a4..a8f26eceda4 100644 --- a/src/docs/sphinx/buildGuide/Dependencies.rst +++ b/src/docs/sphinx/buildGuide/Dependencies.rst @@ -25,6 +25,7 @@ Adiak_ 0.2.0 :code:`ENABLE_CALIPER` :code:`ADIAK_DIR` Caliper_ 2.4.0 :code:`ENABLE_CALIPER` :code:`CALIPER_DIR` Instrumentation and performance profiling library. conduit_ 0.5.0 *mandatory* :code:`CONDUIT_DIR` Simplified Data Exchange for HPC Simulations. CHAI_ 2.2.2 *mandatory* :code:`CHAI_DIR` Copy-hiding array abstraction to automatically migrate data between memory spaces. +cpptrace_ 1.0.0 :code:`ENABLE_CPPTRACE` :code:`CPPTRACE_DIR` Optional stack trace library that captures full throw-site stack traces (including STL frames). RAJA_ 0.12.1 *mandatory* :code:`RAJA_DIR` Collection of C++ software abstractions that enable architecture portability for HPC applications. hdf5_ 1.10.5 *mandatory* :code:`HDF5_DIR` High-performance data management and storage suite. mathpresso_ 2015-12-15 :code:`ENABLE_MATHPRESSO` :code:`MATHPRESSO_DIR` Mathematical Expression Parser and JIT Compiler. @@ -56,6 +57,7 @@ uncrustify_ 401a409 :code:`ENABLE_UNCRUSTIFY` :code:`UNCRUSTIFY_EXECUTABL .. _Caliper: https://github.com/LLNL/Caliper .. _conduit: https://github.com/LLNL/conduit .. _CHAI : https://github.com/LLNL/CHAI +.. _cpptrace : https://github.com/jeremy-rifkin/cpptrace .. _RAJA : https://github.com/LLNL/RAJA .. _hdf5 : https://portal.hdfgroup.org/display/HDF5/HDF5 .. _mathpresso : https://github.com/kobalicek/mathpresso From 473d53a9161bb30fc7b43e82a111d86c469e76ab Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 5 May 2026 17:30:00 +0200 Subject: [PATCH 08/12] fix default in BuildProcess --- src/docs/sphinx/buildGuide/BuildProcess.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/sphinx/buildGuide/BuildProcess.rst b/src/docs/sphinx/buildGuide/BuildProcess.rst index 25ab8af4a4d..88d5a4e914c 100644 --- a/src/docs/sphinx/buildGuide/BuildProcess.rst +++ b/src/docs/sphinx/buildGuide/BuildProcess.rst @@ -70,7 +70,7 @@ Option Default Explanation ``ENABLE_CUDA_NVTOOLSEXT`` ``OFF`` Enable CUDA NVTX user instrumentation (via GEOS_MARK_SCOPE or GEOS_MARK_FUNCTION macros) ``ENABLE_HIP`` ``OFF`` Build with HIP/ROCM (also applies to TPLs) ``ENABLE_DOCS`` ``ON`` Build documentation (Sphinx and Doxygen) -``ENABLE_CPPTRACE`` ``ON`` Enable cpptrace stack traces +``ENABLE_CPPTRACE`` ``OFF`` Enable cpptrace stack traces ``ENABLE_WARNINGS_AS_ERRORS`` ``ON`` Treat all warnings as errors ``ENABLE_PVTPackage`` ``ON`` Enable PVTPackage library (required for compositional flow runs) ``ENABLE_TOTALVIEW_OUTPUT`` ``OFF`` Enables TotalView debugger custom view of GEOS data structures From 5a981de50d97effeaca0e20b97b56802dac8f98e Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 5 May 2026 18:05:02 +0200 Subject: [PATCH 09/12] fix regex --- src/coreComponents/common/logger/ErrorHandling.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/common/logger/ErrorHandling.cpp b/src/coreComponents/common/logger/ErrorHandling.cpp index 7eefeb74f3c..75dd7f98ec1 100644 --- a/src/coreComponents/common/logger/ErrorHandling.cpp +++ b/src/coreComponents/common/logger/ErrorHandling.cpp @@ -213,7 +213,7 @@ DiagnosticMsgBuilder & DiagnosticMsgBuilder::addCallStackInfo( std::string_view std::istringstream iss( str ); std::string stackLine; - std::regex lvArrayPattern( R"(Frame \d+: \S+)" ); + std::regex lvArrayPattern( R"(Frame \d+:\s*)" ); std::regex cpptracePattern( R"(^\s*#\d+\s+)" ); while( std::getline( iss, stackLine ) ) From 0f9d2023b3a0630a712413719c6606bb18d04976 Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 5 May 2026 18:06:02 +0200 Subject: [PATCH 10/12] add signal-safe stack trace method --- src/coreComponents/common/initializeEnvironment.cpp | 2 +- src/coreComponents/common/logger/StackTrace.cpp | 5 +++++ src/coreComponents/common/logger/StackTrace.hpp | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/common/initializeEnvironment.cpp b/src/coreComponents/common/initializeEnvironment.cpp index 90f00b5a731..2bc60ddc860 100644 --- a/src/coreComponents/common/initializeEnvironment.cpp +++ b/src/coreComponents/common/initializeEnvironment.cpp @@ -110,7 +110,7 @@ void setupLogger() ExternalErrorHandler::instance().flush( "before signal error output" ); // error message output - std::string const stackHistory = StackTrace::stackTrace(); + std::string const stackHistory = StackTrace::signalSafeStackTrace(); DiagnosticMsg diagnosticMsg; ErrorLogger::global().flushErrorMsg( DiagnosticMsgBuilder::init( diagnosticMsg, MsgType::ExternalError, "", diff --git a/src/coreComponents/common/logger/StackTrace.cpp b/src/coreComponents/common/logger/StackTrace.cpp index c94a483f310..04a7cfa176f 100644 --- a/src/coreComponents/common/logger/StackTrace.cpp +++ b/src/coreComponents/common/logger/StackTrace.cpp @@ -40,6 +40,11 @@ std::string StackTrace::stackTrace() #endif } +std::string StackTrace::signalSafeStackTrace() +{ + return LvArray::system::stackTrace( true ); +} + #ifdef GEOS_USE_CPPTRACE cpptrace::formatter & StackTrace::formatter() { diff --git a/src/coreComponents/common/logger/StackTrace.hpp b/src/coreComponents/common/logger/StackTrace.hpp index 91e01d3869f..44e2a38d090 100644 --- a/src/coreComponents/common/logger/StackTrace.hpp +++ b/src/coreComponents/common/logger/StackTrace.hpp @@ -41,9 +41,16 @@ class StackTrace /** * @brief Get a stack trace for the current thread. * @return The stack trace as a string. + * @note Not signal-safe. Use signalSafeStackTrace() from inside a signal handler. */ static std::string stackTrace(); + /** + * @brief Get a stack trace from a context where signal-safety is required. + * @return The stack trace as a string. + */ + static std::string signalSafeStackTrace(); + #ifdef GEOS_USE_CPPTRACE /** * @brief Access the configured cpptrace formatter. From e88e821756f12475b762087233e3432f19d037c0 Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 5 May 2026 18:12:09 +0200 Subject: [PATCH 11/12] modify types --- src/coreComponents/common/logger/StackTrace.cpp | 6 +++--- src/coreComponents/common/logger/StackTrace.hpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreComponents/common/logger/StackTrace.cpp b/src/coreComponents/common/logger/StackTrace.cpp index 04a7cfa176f..1fa59d0be60 100644 --- a/src/coreComponents/common/logger/StackTrace.cpp +++ b/src/coreComponents/common/logger/StackTrace.cpp @@ -46,9 +46,9 @@ std::string StackTrace::signalSafeStackTrace() } #ifdef GEOS_USE_CPPTRACE -cpptrace::formatter & StackTrace::formatter() +cpptrace::formatter const & StackTrace::formatter() { - static cpptrace::formatter fmt = cpptrace::formatter{} + static cpptrace::formatter const fmt = cpptrace::formatter{} .header( "" ) .addresses( cpptrace::formatter::address_mode::none ) .paths( cpptrace::formatter::path_mode::basename ) @@ -81,7 +81,7 @@ cpptrace::formatter & StackTrace::formatter() return fmt; } -std::string StackTrace::formatStackTrace( cpptrace::v1::stacktrace stacktrace ) +std::string StackTrace::formatStackTrace( cpptrace::stacktrace const & stacktrace ) { return formatter().format( stacktrace ); } diff --git a/src/coreComponents/common/logger/StackTrace.hpp b/src/coreComponents/common/logger/StackTrace.hpp index 44e2a38d090..e09cce7a0e5 100644 --- a/src/coreComponents/common/logger/StackTrace.hpp +++ b/src/coreComponents/common/logger/StackTrace.hpp @@ -56,14 +56,14 @@ class StackTrace * @brief Access the configured cpptrace formatter. * @return The formatter instance. */ - static cpptrace::formatter & formatter(); + static cpptrace::formatter const & formatter(); /** * @brief Format a cpptrace stacktrace using the configured formatter. * @param stacktrace The cpptrace stack trace to format. * @return Formatted stack trace string. */ - static std::string formatStackTrace( cpptrace::v1::stacktrace stacktrace ); + static std::string formatStackTrace( cpptrace::stacktrace const & stacktrace ); #endif }; From 197c7ee244d1074e492a78e33014425e4a1dc29f Mon Sep 17 00:00:00 2001 From: kdrienCG Date: Tue, 5 May 2026 18:12:31 +0200 Subject: [PATCH 12/12] move include position --- src/coreComponents/common/initializeEnvironment.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/common/initializeEnvironment.cpp b/src/coreComponents/common/initializeEnvironment.cpp index 2bc60ddc860..89d071ef26c 100644 --- a/src/coreComponents/common/initializeEnvironment.cpp +++ b/src/coreComponents/common/initializeEnvironment.cpp @@ -22,11 +22,11 @@ #include "logger/ErrorHandling.hpp" #include "logger/ExternalErrorHandler.hpp" #include +#include "logger/StackTrace.hpp" // TPL includes #include #include #include -#include "logger/StackTrace.hpp" #include "umpire/util/MemoryResourceTraits.hpp" #include "umpire/util/Platform.hpp"