feat: add cpptrace for better stack traces #4042
Conversation
|
@kdrienCG Is there a discussion somewhere about whether we want to add this dependency? |
|
@rrsettgast yes, we discussed this internally. There is value in having this TPL for debugging deeper issues. We can talk if you wish. |
@herve-gross That decision being made without consulting others on the core team is inappropriate. The inclusion of this package covers the fundamental problem in the approach to c++ exceptions in an HPC simulation code. There are simpler solutions...like output stack on the throw. |
| 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() ) ); |
There was a problem hiding this comment.
| 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() ) ); | |
| while( std::getline( iss, stackLine ) ) | |
| { | |
| std::smatch m; | |
| if( std::regex_search( stackLine, m, lvArrayPattern ) || | |
| std::regex_search( stackLine, m, cpptracePattern ) ) | |
| { | |
| m_errorMsg.m_isValidStackTrace = true; | |
| m_errorMsg.m_sourceCallStack.push_back( m.suffix().str() ); | |
| } | |
| } |
There was a problem hiding this comment.
To be tested but might be interesting to leverage std::smatch to its max
| * @note Not signal-safe. Use signalSafeStackTrace() from inside a signal handler. | ||
| */ | ||
| static std::string stackTrace(); | ||
|
|
There was a problem hiding this comment.
| /** | |
| * @brief Get a stack trace from a context where signal-safety is required. | |
| * @return The stack trace as a string. | |
| * @note If signal-safe is required, revert back to LvArray::system | |
| */ |
There was a problem hiding this comment.
I think it is worth documenting here that behavior for signal-safe is dropping cpptrace
| catch( geos::Exception & e ) | ||
| }; | ||
|
|
||
| auto onGeosException = [&]( geos::Exception & e ) | ||
| { // GEOS generated exceptions management | ||
| #ifdef GEOS_USE_CPPTRACE | ||
| std::string const stacktrace = StackTrace::formatStackTrace( cpptrace::from_current_exception() ); |
There was a problem hiding this comment.
Looks like the MACRO dispach will occur at each new lambda-exception. Maybe worth passing a callback through the lambda's interface and dispatch all below ? In case we add more of this and the duplication spread
| int main( int argc, char *argv[] ) | ||
| { | ||
| try | ||
| auto runMain = [&] |
(Requires TPL PR #347)
This PR aims to improve the stack trace output when an error is thrown.
When GEOS crashes from a C++ exception, the stack trace we log is not really useful: it points at
main.cppinstead of the code that actually threw, missing on valuable informations for devs. This is not a bug in the error handler, it is how the C++ runtime works.cpptrace solves this by providing a mechanism to get stack traces from thrown exceptions, that will make us able to know exactly where the code went.
Here is an example defining a
myThrowingFunction()incorrectly using amapdirectly (written in themain.cppfor convenience)Without cpptrace:
With cpptrace:
(truncated to fit the PR description)
We have a detailled stack trace with the name of the function that throws and the correct line and character position.