diff options
| author | Duncan Horn | 2025-09-27 02:09:34 -0700 |
|---|---|---|
| committer | GitHub | 2025-09-27 11:09:34 +0200 |
| commit | 0e772cc0d29e7518f84a1ad11aa179167a6ab6bc (patch) | |
| tree | c5e707777ac07e5ff607395449f68092cc380da1 /src/catch2 | |
| parent | 3bcd0a4e74b2bb5f6ec80ad464775442af84343c (diff) | |
| download | catch3-0e772cc0d29e7518f84a1ad11aa179167a6ab6bc.tar.gz | |
Allow composability of unhandled exception filters (#3033)
The change is very simple. If a handler previously existed, Catch2 will invoke it after printing out its output. I've also updated the comment to better reflect that it's returning EXCEPTION_CONTINUE_SEARCH even in scenarios where the exception is one that the library cares about.
Diffstat (limited to 'src/catch2')
| -rw-r--r-- | src/catch2/internal/catch_fatal_condition_handler.cpp | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/src/catch2/internal/catch_fatal_condition_handler.cpp b/src/catch2/internal/catch_fatal_condition_handler.cpp index 26f894d6..3dfa1383 100644 --- a/src/catch2/internal/catch_fatal_condition_handler.cpp +++ b/src/catch2/internal/catch_fatal_condition_handler.cpp @@ -86,23 +86,27 @@ namespace Catch { { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, }; + // Since we do not support multiple instantiations, we put these + // into global variables and rely on cleaning them up in outlined + // constructors/destructors + static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr; + + static LONG CALLBACK topLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) { for (auto const& def : signalDefs) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { reportFatal(def.name); } } - // If its not an exception we care about, pass it along. + // If a filter was previously registered, invoke it + if (previousTopLevelExceptionFilter) { + return previousTopLevelExceptionFilter(ExceptionInfo); + } + // Otherwise, pass along all exceptions. // This stops us from eating debugger breaks etc. return EXCEPTION_CONTINUE_SEARCH; } - // Since we do not support multiple instantiations, we put these - // into global variables and rely on cleaning them up in outlined - // constructors/destructors - static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr; - - // For MSVC, we reserve part of the stack memory for handling // memory overflow structured exception. FatalConditionHandler::FatalConditionHandler() { |