Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/coreComponents/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ set( common_headers
MemoryInfos.hpp
logger/GeosExceptions.hpp
logger/Logger.hpp
logger/ErrorHandling.hpp
logger/ErrorHandler.hpp
logger/ErrorLogger.hpp
logger/ExternalErrorHandler.hpp
MpiWrapper.hpp
Path.hpp
Expand Down Expand Up @@ -80,7 +81,8 @@ set( common_sources
format/StringUtilities.cpp
logger/GeosExceptions.cpp
logger/Logger.cpp
logger/ErrorHandling.cpp
logger/ErrorHandler.cpp
logger/ErrorLogger.cpp
logger/ExternalErrorHandler.cpp
BufferAllocator.cpp
MemoryInfos.cpp
Expand Down
90 changes: 21 additions & 69 deletions src/coreComponents/common/initializeEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
#include "Path.hpp"
#include "LvArray/src/system.hpp"
#include "common/LifoStorageCommon.hpp"
#include "logger/ErrorHandling.hpp"
#include "logger/ExternalErrorHandler.hpp"
#include "logger/ErrorHandler.hpp"
#include <umpire/TypedAllocator.hpp>
// TPL includes
#include <umpire/ResourceManager.hpp>
Expand Down Expand Up @@ -68,73 +67,13 @@ void setupLogger()
logger::InitializeLogger();
#endif

{ // setup error handling (using LvArray helper system functions)

ExternalErrorHandler::instance().enableStderrPipeDeviation( true );

///// set external error handling behaviour /////
ExternalErrorHandler::instance().setErrorHandling( []( string_view errorMsg,
string_view detectionLocation )
{
// Filter out INFO level messages from external libraries (e.g., VTK)
// ( error / signal lambda would calls either an error function or an info function, depending on a filtering function )
if( ExternalErrorHandler::isNotAnErrorMsg( errorMsg ) )
{
// Just print the message without error formatting
GEOS_LOG( errorMsg );
return;
}
else
{
std::string const stackHistory = LvArray::system::stackTrace( true );
DiagnosticMsg diagnosticMsg;
ErrorLogger::global().flushErrorMsg( DiagnosticMsgBuilder::init( diagnosticMsg,
MsgType::Error, errorMsg,
::geos::logger::internal::g_rank )
.addCallStackInfo( stackHistory )
.addDetectionLocation( detectionLocation )
.getDiagnosticMsg() );

// we do not terminate the program as 1. the error could be non-fatal, 2. there may be more messages to output.
}
} );

///// set signal handling behaviour /////
LvArray::system::setSignalHandling( []( int const signal )
{
// Disable signal handling to prevent catching exit signal (infinite loop)
LvArray::system::setSignalHandling( nullptr );

// first of all, external error can await to be output, we must output them
ExternalErrorHandler::instance().flush( "before signal error output" );

// error message output
std::string const stackHistory = LvArray::system::stackTrace( true );
DiagnosticMsg diagnosticMsg;
ErrorLogger::global().flushErrorMsg( DiagnosticMsgBuilder::init( diagnosticMsg,
MsgType::ExternalError, "",
::geos::logger::internal::g_rank )
.addSignal( signal )
.addCallStackInfo( stackHistory )
.getDiagnosticMsg() );

// call program termination
LvArray::system::callErrorHandler();
} );

///// set Post-Handled Error behaviour /////
LvArray::system::setErrorHandler( []()
{
#if defined( GEOS_USE_MPI )
int mpi = 0;
MPI_Initialized( &mpi );
if( mpi )
{
MPI_Abort( MPI_COMM_WORLD, EXIT_FAILURE );
}
#endif
std::abort();
} );
{
ErrorHandler defaultErrorHandler;
defaultErrorHandler.setLogger( &ErrorLogger::global() );
defaultErrorHandler.enableExternalErrorPipeDeviation( true );
defaultErrorHandler.setProgramAborter( abortGeos );

ErrorHandler::setupErrorHandlingStrategy( std::move( defaultErrorHandler ) );
}
}

Expand Down Expand Up @@ -339,4 +278,17 @@ void cleanupEnvironment( bool inError )
finalizeMPI( inError );
}

void abortGeos()
{
#if defined( GEOS_USE_MPI )
int mpi = 0;
MPI_Initialized( &mpi );
if( mpi )
{
MPI_Abort( MPI_COMM_WORLD, EXIT_FAILURE );
}
#endif
std::abort();
}

} // namespace geos
5 changes: 5 additions & 0 deletions src/coreComponents/common/initializeEnvironment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ void pushStatsIntoAdiak( string const & name, T const value )
#endif
}

/**
* @brief Post-Handling error behaviour
*/
void abortGeos();

} // namespace geos

#endif // GEOS_COMMON_INITIALIZEENVIRONMENT_HPP_
142 changes: 142 additions & 0 deletions src/coreComponents/common/logger/ErrorHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* ------------------------------------------------------------------------------------------------------------
* 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 ErrorHandler.cpp
*/

#include "ErrorHandler.hpp"

#include "ExternalErrorHandler.hpp"
#include "Logger.hpp"

namespace geos
{

ErrorHandler ErrorHandler::s_errorHandlerInstance;

ErrorHandler::ErrorHandler()
: m_logger( &ErrorLogger::global() )
, m_abortingFunctor( []() { std::abort(); } )
{}

ErrorHandler const & ErrorHandler::getInstance()
{
return s_errorHandlerInstance;
}

void ErrorHandler::setupErrorHandlingStrategy( ErrorHandler && instance )
{
s_errorHandlerInstance = instance;
s_errorHandlerInstance.setupExternalErrorManagment();
s_errorHandlerInstance.setupSignalHandling();
s_errorHandlerInstance.setupLvArrayErrorHandling();
}

void ErrorHandler::setupExternalErrorManagment()
{
ExternalErrorHandler::instance().enableStderrPipeDeviation( true );

ExternalErrorHandler::instance().setErrorHandling( [&]( string_view errorMsg,
string_view detectionLocation )
{
// Filter out INFO level messages from external libraries (e.g., VTK)
// ( error / signal lambda would calls either an error function or an info function, depending on a filtering function )
if( ExternalErrorHandler::isNotAnErrorMsg( errorMsg ) )
{
// Just print the message without error formatting
GEOS_LOG( errorMsg );
return;
}
else
{
std::string const stackHistory = LvArray::system::stackTrace( true );
DiagnosticMsg diagnosticMsg;
m_logger->flushErrorMsg( DiagnosticMsgBuilder::init( diagnosticMsg,
MsgType::Error, errorMsg,
::geos::logger::internal::g_rank )
.addCallStackInfo( stackHistory )
.addDetectionLocation( detectionLocation )
.setCause( "Error pipe output from a dependency" )
.getDiagnosticMsg() );

// we do not terminate the program as 1. the error could be non-fatal, 2. there may be more messages to output.
}
} );
}

void ErrorHandler::setupSignalHandling()
{
LvArray::system::setSignalHandling( []( int const signal )
{
// setSignalHandling() cannot take capturing lambda, so we get the instance with the static function.
ErrorHandler const & instance = ErrorHandler::getInstance();

// Disable signal handling to prevent catching exit signal (infinite loop)
LvArray::system::setSignalHandling( nullptr );

// first of all, there can be external error that await to be output
ExternalErrorHandler::instance().flush( "before signal error output" );

// error message output
std::string const stackHistory = LvArray::system::stackTrace( true );
DiagnosticMsg diagnosticMsg;
DiagnosticMsgBuilder::init( diagnosticMsg,
MsgType::ExternalError, "",
::geos::logger::internal::g_rank )
.addSignal( signal )
.addCallStackInfo( stackHistory );
instance.m_logger->flushErrorMsg( diagnosticMsg );

// call program termination
instance.abortProgram();
} );
}

void ErrorHandler::setupLvArrayErrorHandling()
{
LvArray::system::setErrorHandler( [&]()
{
// first of all, there can be external error that await to be output
ExternalErrorHandler::instance().flush( "before LvArray error handling" );

// default error message output
DiagnosticMsg diagnosticMsg;
DiagnosticMsgBuilder::init( diagnosticMsg,
MsgType::ExternalError,
"LvArray Runtime Error",
::geos::logger::internal::g_rank )
.addCallStackInfo( LvArray::system::stackTrace( true ) )
.addDetectionLocation( "LvArray Error Handler" );
m_logger->flushErrorMsg( diagnosticMsg );

// call program termination
abortProgram();
} );
}

void ErrorHandler::manageException( std::exception const & e,
string_view causeMessage,
string_view stackTrace ) const
{
m_logger->flushErrorMsg( m_logger->initCurrentExceptionMessage( MsgType::Exception,
e.what(),
::geos::logger::internal::g_rank )
.setCause( causeMessage )
.addCallStackInfo( stackTrace )
.getDiagnosticMsg());
}

} /* namespace geos */
Loading
Loading