Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorPhil Nash2017-01-12 08:44:00 +0000
committerMartin Hořeňovský2017-01-12 17:31:56 +0100
commit40dbdf6cb2d34d2d056f4292e4b70f0ff6afd562 (patch)
tree4a73df420aa2426c936fe0d79611956558bb9af1
parent70f43d719bfd13e4c1d385e56801139d1a518273 (diff)
downloadcatch3-40dbdf6cb2d34d2d056f4292e4b70f0ff6afd562.tar.gz
Reset signals immediately after use and re-raise orginal signal instead of just exiting
-rw-r--r--include/internal/catch_fatal_condition.hpp66
1 files changed, 41 insertions, 25 deletions
diff --git a/include/internal/catch_fatal_condition.hpp b/include/internal/catch_fatal_condition.hpp
index c6c3489f..1a130a45 100644
--- a/include/internal/catch_fatal_condition.hpp
+++ b/include/internal/catch_fatal_condition.hpp
@@ -12,14 +12,11 @@
namespace Catch {
- // Report the error condition then exit the process
- inline void fatal( std::string const& message, int exitCode ) {
+ // Report the error condition
+ inline void reportFatal( std::string const& message, int exitCode ) {
IContext& context = Catch::getCurrentContext();
IResultCapture* resultCapture = context.getResultCapture();
resultCapture->handleFatalErrorCondition( message );
-
- if( Catch::alwaysTrue() ) // avoids "no return" warnings
- exit( exitCode );
}
} // namespace Catch
@@ -52,7 +49,7 @@ namespace Catch {
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
- fatal(signalDefs[i].name, -i);
+ reportFatal(signalDefs[i].name, -i);
}
}
// If its not an exception we care about, pass it along.
@@ -94,7 +91,10 @@ namespace Catch {
namespace Catch {
- struct SignalDefs { int id; const char* name; };
+ struct SignalDefs {
+ int id;
+ const char* name;
+ };
extern SignalDefs signalDefs[];
SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" },
@@ -103,53 +103,69 @@ namespace Catch {
{ SIGSEGV, "SIGSEGV - Segmentation violation signal" },
{ SIGTERM, "SIGTERM - Termination request signal" },
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
- };
+ };
struct FatalConditionHandler {
+ static bool isSet;
+ static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
+ static stack_t oldSigStack;
+ static char altStackMem[SIGSTKSZ];
+
static void handleSignal( int sig ) {
- for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
- if( sig == signalDefs[i].id )
- fatal( signalDefs[i].name, -sig );
- fatal( "<unknown signal>", -sig );
+ std::string name = "<unknown signal>";
+ for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
+ SignalDefs &def = signalDefs[i];
+ if (sig == def.id) {
+ name = def.name;
+ sigaction(def.id, &oldSigActions[i], CATCH_NULL);
+ break;
+ }
+ }
+ reportFatal(name, -sig);
+ raise( sig );
}
- FatalConditionHandler(): m_isSet(true), m_altStackMem(new char[SIGSTKSZ]) {
+ FatalConditionHandler() {
+ isSet = true;
stack_t sigStack;
- sigStack.ss_sp = m_altStackMem;
+ sigStack.ss_sp = altStackMem;
sigStack.ss_size = SIGSTKSZ;
sigStack.ss_flags = 0;
- sigaltstack(&sigStack, &m_oldSigStack);
+ sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = { 0 };
sa.sa_handler = handleSignal;
sa.sa_flags = SA_ONSTACK;
for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
- sigaction(signalDefs[i].id, &sa, &m_oldSigActions[i]);
+ sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
}
}
+
+
~FatalConditionHandler() {
reset();
- delete[] m_altStackMem;
}
void reset() {
- if( m_isSet ) {
+ if( isSet ) {
// Set signals back to previous values -- hopefully nobody overwrote them in the meantime
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
- sigaction(signalDefs[i].id, &m_oldSigActions[i], CATCH_NULL);
+ sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
}
// Return the old stack
- sigaltstack(&m_oldSigStack, CATCH_NULL);
- m_isSet = false;
+ sigaltstack(&oldSigStack, CATCH_NULL);
+ isSet = false;
}
}
- bool m_isSet;
// C++03 doesn't allow auto_ptr<T[]>, so we have manage the memory ourselves
- char* m_altStackMem;
- struct sigaction m_oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
- stack_t m_oldSigStack;
};
+
+ bool FatalConditionHandler::isSet = false;
+ struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {} ;//[sizeof(signalDefs)/sizeof(SignalDefs)];
+ stack_t FatalConditionHandler::oldSigStack = {};
+ char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
+
} // namespace Catch