mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-20 12:26:10 +01:00
Fix disengage failure logs for FatalConditionHandlerGuard
FatalConditionHandlerGuard is used within RunContext::invokeActiveTestCase(). The intent of this guard is to avoid binary crash without failed test being reported. Still in case FatalConditionHandlerGuard destructor being called during stack unwinding AND finds unexpected top-level filter for SEH unhandled exception, the binary may still crash. As result of such crash the original exception details are being hidden. As the Catch2 provides only `CATCH_CATCH_ANON` macro, with no access to exception details by design, looks like the best way to handle issue is to: - state requirements explicitly by `noexcept` specifier - use `Catch::cerr()` to print out possible issue notification Signed-off-by: Kochetkov, Yuriy <yuriyx.kochetkov@intel.com>
This commit is contained in:
parent
7882f7359e
commit
2ce64d1d8f
@ -40,7 +40,7 @@ namespace Catch {
|
|||||||
// If neither SEH nor signal handling is required, the handler impls
|
// If neither SEH nor signal handling is required, the handler impls
|
||||||
// do not have to do anything, and can be empty.
|
// do not have to do anything, and can be empty.
|
||||||
void FatalConditionHandler::engage_platform() {}
|
void FatalConditionHandler::engage_platform() {}
|
||||||
void FatalConditionHandler::disengage_platform() {}
|
void FatalConditionHandler::disengage_platform() noexcept {}
|
||||||
FatalConditionHandler::FatalConditionHandler() = default;
|
FatalConditionHandler::FatalConditionHandler() = default;
|
||||||
FatalConditionHandler::~FatalConditionHandler() = default;
|
FatalConditionHandler::~FatalConditionHandler() = default;
|
||||||
|
|
||||||
@ -124,9 +124,11 @@ namespace Catch {
|
|||||||
previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter);
|
previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FatalConditionHandler::disengage_platform() {
|
void FatalConditionHandler::disengage_platform() noexcept {
|
||||||
if (SetUnhandledExceptionFilter(previousTopLevelExceptionFilter) != topLevelExceptionFilter) {
|
if (SetUnhandledExceptionFilter(previousTopLevelExceptionFilter) != topLevelExceptionFilter) {
|
||||||
CATCH_RUNTIME_ERROR("Could not restore previous top level exception filter");
|
Catch::cerr()
|
||||||
|
<< "Unexpected SEH unhandled exception filter on disengage."
|
||||||
|
<< " The filter was restored, but might be rolled back unexpectedly.";
|
||||||
}
|
}
|
||||||
previousTopLevelExceptionFilter = nullptr;
|
previousTopLevelExceptionFilter = nullptr;
|
||||||
}
|
}
|
||||||
@ -168,7 +170,7 @@ namespace Catch {
|
|||||||
static stack_t oldSigStack{};
|
static stack_t oldSigStack{};
|
||||||
static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
|
static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
|
||||||
|
|
||||||
static void restorePreviousSignalHandlers() {
|
static void restorePreviousSignalHandlers() noexcept {
|
||||||
// We set signal handlers back to the previous ones. Hopefully
|
// We set signal handlers back to the previous ones. Hopefully
|
||||||
// nobody overwrote them in the meantime, and doesn't expect
|
// nobody overwrote them in the meantime, and doesn't expect
|
||||||
// their signal handlers to live past ours given that they
|
// their signal handlers to live past ours given that they
|
||||||
@ -231,7 +233,7 @@ namespace Catch {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void FatalConditionHandler::disengage_platform() {
|
void FatalConditionHandler::disengage_platform() noexcept {
|
||||||
restorePreviousSignalHandlers();
|
restorePreviousSignalHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ namespace Catch {
|
|||||||
// Should be if-defed to work on current platform, can assume
|
// Should be if-defed to work on current platform, can assume
|
||||||
// engage-disengage 1:1 pairing.
|
// engage-disengage 1:1 pairing.
|
||||||
void engage_platform();
|
void engage_platform();
|
||||||
void disengage_platform();
|
void disengage_platform() noexcept;
|
||||||
public:
|
public:
|
||||||
// Should also have platform-specific implementations as needed
|
// Should also have platform-specific implementations as needed
|
||||||
FatalConditionHandler();
|
FatalConditionHandler();
|
||||||
@ -44,7 +44,7 @@ namespace Catch {
|
|||||||
engage_platform();
|
engage_platform();
|
||||||
}
|
}
|
||||||
|
|
||||||
void disengage() {
|
void disengage() noexcept {
|
||||||
assert(m_started && "Handler cannot be uninstalled without being installed first");
|
assert(m_started && "Handler cannot be uninstalled without being installed first");
|
||||||
m_started = false;
|
m_started = false;
|
||||||
disengage_platform();
|
disengage_platform();
|
||||||
|
Loading…
Reference in New Issue
Block a user