diff --git a/include/internal/catch_fatal_condition.hpp b/include/internal/catch_fatal_condition.hpp index dd21d590..e57d8810 100644 --- a/include/internal/catch_fatal_condition.hpp +++ b/include/internal/catch_fatal_condition.hpp @@ -60,22 +60,41 @@ namespace Catch { fatal( "", -sig ); } - FatalConditionHandler() : m_isSet( true ) { - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) - signal( signalDefs[i].id, handleSignal ); + FatalConditionHandler(): m_isSet(true), m_altStackMem(new char[SIGSTKSZ]) { + stack_t sigStack; + sigStack.ss_sp = m_altStackMem; + sigStack.ss_size = SIGSTKSZ; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &m_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]); + } } ~FatalConditionHandler() { reset(); + delete[] m_altStackMem; } void reset() { if( m_isSet ) { - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) - signal( signalDefs[i].id, SIG_DFL ); + // 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); + } + // Return the old stack + sigaltstack(&m_oldSigStack, CATCH_NULL); m_isSet = false; } } bool m_isSet; + // C++03 doesn't allow auto_ptr, so we have manage the memory ourselves + char* m_altStackMem; + struct sigaction m_oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; + stack_t m_oldSigStack; }; } // namespace Catch