From 1ad233da8680c7f974d1119c1a59768ed8dcc2bc Mon Sep 17 00:00:00 2001 From: Julian Brost Date: Tue, 20 Oct 2020 14:02:42 +0200 Subject: [PATCH] Add some comments to __cxa_throw Maybe this will save the next person who has to look at this code some time. Please don't blame me for the implementation, I'm just trying to reconstruct what it does. --- lib/base/exception.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/base/exception.cpp b/lib/base/exception.cpp index fa301fe4f..17921a2f6 100644 --- a/lib/base/exception.cpp +++ b/lib/base/exception.cpp @@ -101,6 +101,13 @@ void icinga::RethrowUncaughtException() extern "C" void __cxa_throw(void *obj, TYPEINFO_TYPE *pvtinfo, void (*dest)(void *)) { + /* This function overrides an internal function of libstdc++ that is called when a C++ exception is thrown in order + * to capture as much information as possible at that time and then call the original implementation. This + * information includes: + * - stack trace (for later use in DiagnosticInformation) + * - context trace (for later use in DiagnosticInformation) + */ + auto *tinfo = static_cast(pvtinfo); typedef void (*cxa_throw_fn)(void *, std::type_info *, void (*)(void *)) __attribute__((noreturn)); @@ -112,6 +119,7 @@ void __cxa_throw(void *obj, TYPEINFO_TYPE *pvtinfo, void (*dest)(void *)) l_LastExceptionDest.reset(new DestCallback(dest)); #endif /* !defined(__GLIBCXX__) && !defined(_WIN32) */ + // resolve symbol to original implementation of __cxa_throw for the call at the end of this function if (real_cxa_throw == nullptr) real_cxa_throw = (cxa_throw_fn)dlsym(RTLD_NEXT, "__cxa_throw"); @@ -121,10 +129,12 @@ void __cxa_throw(void *obj, TYPEINFO_TYPE *pvtinfo, void (*dest)(void *)) if (!uex) { #endif /* NO_CAST_EXCEPTION */ + // save the current stack trace in a thread-local variable boost::stacktrace::stacktrace stack; SetLastExceptionStack(stack); #ifndef NO_CAST_EXCEPTION + // save the current stack trace in the boost exception error info if the exception is a boost::exception if (ex && !boost::get_error_info(*ex)) *ex << StackTraceErrorInfo(stack); } @@ -134,6 +144,7 @@ void __cxa_throw(void *obj, TYPEINFO_TYPE *pvtinfo, void (*dest)(void *)) SetLastExceptionContext(context); #ifndef NO_CAST_EXCEPTION + // save the current context trace in the boost exception error info if the exception is a boost::exception if (ex && !boost::get_error_info(*ex)) *ex << ContextTraceErrorInfo(context); #endif /* NO_CAST_EXCEPTION */