From bc9f7d2f8760d00303ae13be0b24bf246f249b85 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 21 Feb 2014 23:23:01 -0700 Subject: [PATCH] refactor SignalRegistrar interface --- include/avian/system/signal.h | 26 ++++++++++++++-------- src/compile.cpp | 8 +++---- src/system/posix/signal.cpp | 41 ++++++++++++++++++++++++++--------- src/system/windows/signal.cpp | 18 ++++++++------- 4 files changed, 62 insertions(+), 31 deletions(-) diff --git a/include/avian/system/signal.h b/include/avian/system/signal.h index 15581ec7d3..590ab7a44f 100644 --- a/include/avian/system/signal.h +++ b/include/avian/system/signal.h @@ -36,21 +36,29 @@ class SignalRegistrar { void** thread) = 0; }; + enum Signal { + // "Segmentation fault" exceptions (mostly null pointer dereference, but + // generally access to any non-mapped memory) + SegFault, + + DivideByZero, + }; + SignalRegistrar(); ~SignalRegistrar(); - // Register a handler for segfault signals. - // After this method call, any segfault exceptions (mostly null pointer - // dereference, but generally access to any non-mapped memory) will be handled - // by the given handler. Pass null (0) to unregister a handler. + // Register a handler for the given signal. + // After this method call, anytime the given signal is raised, it will be + // handled by the given handler. // Returns true upon success, false upon failure - bool handleSegFault(Handler* handler); + bool registerHandler(Signal signal, Handler* handler); - // Register a handler for divide-by-zero signals. - // After this method call, any divide-by-zero exceptions will be handled by - // the given handler. Pass null (0) to unregister a handler. + // Unregister a handler for the given signal. + // After this method call, the given signal will no longer be handled (or, + // rather, it go back to being handled by whatever was registered to handle it + // before us). // Returns true upon success, false upon failure - bool handleDivideByZero(Handler* handler); + bool unregisterHandler(Signal signal); // Set the directory that a crash dump will be written to should an unhandled // exception be thrown. diff --git a/src/compile.cpp b/src/compile.cpp index f716fe4e1f..0f41e6c73a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -8930,8 +8930,8 @@ class MyProcessor: public Processor { compilationHandlers->dispose(allocator); - signals.handleSegFault(0); - signals.handleDivideByZero(0); + signals.unregisterHandler(SignalRegistrar::SegFault); + signals.unregisterHandler(SignalRegistrar::DivideByZero); signals.setCrashDumpDirectory(0); allocator->free(this, sizeof(*this)); @@ -9124,10 +9124,10 @@ class MyProcessor: public Processor { #endif segFaultHandler.m = t->m; - expect(t, signals.handleSegFault(&segFaultHandler)); + expect(t, signals.registerHandler(SignalRegistrar::SegFault, &segFaultHandler)); divideByZeroHandler.m = t->m; - expect(t, signals.handleDivideByZero(÷ByZeroHandler)); + expect(t, signals.registerHandler(SignalRegistrar::DivideByZero, ÷ByZeroHandler)); } virtual void callWithCurrentContinuation(Thread* t, object receiver) { diff --git a/src/system/posix/signal.cpp b/src/system/posix/signal.cpp index 67c17055d4..bd4581697d 100644 --- a/src/system/posix/signal.cpp +++ b/src/system/posix/signal.cpp @@ -186,21 +186,42 @@ bool SignalRegistrar::Data::registerHandler(Handler* handler, int index) } } -bool SignalRegistrar::handleSegFault(Handler* handler) +bool SignalRegistrar::registerHandler(Signal signal, Handler* handler) { - if(!data->registerHandler(handler, posix::SegFaultSignalIndex)) { - return false; - } - if (posix::AltSegFaultSignal != posix::InvalidSignal) { - return data->registerHandler(handler, posix::AltSegFaultSignalIndex); - } else { - return true; + switch(signal) { + case SegFault: + if(!data->registerHandler(handler, posix::SegFaultSignalIndex)) { + return false; + } + if (posix::AltSegFaultSignal != posix::InvalidSignal) { + return data->registerHandler(handler, posix::AltSegFaultSignalIndex); + } else { + return true; + } + case DivideByZero: + return data->registerHandler(handler, posix::DivideByZeroSignalIndex); + default: + crash(); } } -bool SignalRegistrar::handleDivideByZero(Handler* handler) +bool SignalRegistrar::unregisterHandler(Signal signal) { - return data->registerHandler(handler, posix::DivideByZeroSignalIndex); + switch(signal) { + case SegFault: + if(!data->registerHandler(0, posix::SegFaultSignalIndex)) { + return false; + } + if (posix::AltSegFaultSignal != posix::InvalidSignal) { + return data->registerHandler(0, posix::AltSegFaultSignalIndex); + } else { + return true; + } + case DivideByZero: + return data->registerHandler(0, posix::DivideByZeroSignalIndex); + default: + crash(); + } } void SignalRegistrar::setCrashDumpDirectory(const char*) diff --git a/src/system/windows/signal.cpp b/src/system/windows/signal.cpp index 22bd9cc286..7477d10037 100644 --- a/src/system/windows/signal.cpp +++ b/src/system/windows/signal.cpp @@ -36,8 +36,6 @@ namespace avian { namespace system { namespace windows { -const unsigned SegFaultIndex = 0; -const unsigned DivideByZeroIndex = 1; const unsigned HandlerCount = 2; @@ -161,10 +159,10 @@ LONG CALLBACK handleException(LPEXCEPTION_POINTERS e) { SignalRegistrar::Handler* handler = 0; if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { - handler = SignalRegistrar::Data::instance->handlers[SegFaultIndex]; + handler = SignalRegistrar::Data::instance->handlers[SignalRegistrar::SegFault]; } else if (e->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO) { - handler = SignalRegistrar::Data::instance->handlers[DivideByZeroIndex]; + handler = SignalRegistrar::Data::instance->handlers[SignalRegistrar::DivideByZero]; } if (handler) { @@ -219,6 +217,10 @@ SignalRegistrar::~SignalRegistrar() bool SignalRegistrar::Data::registerHandler(Handler* handler, int index) { + if(index != SegFault && index != DivideByZero) { + crash(); + } + if (handler) { handlers[index] = handler; @@ -271,14 +273,14 @@ NO_RETURN void crash() abort(); } -bool SignalRegistrar::handleSegFault(Handler* handler) +bool SignalRegistrar::registerHandler(Signal signal, Handler* handler) { - return data->registerHandler(handler, windows::SegFaultIndex); + return data->registerHandler(handler, signal); } -bool SignalRegistrar::handleDivideByZero(Handler* handler) +bool SignalRegistrar::unregisterHandler(Signal signal) { - return data->registerHandler(handler, windows::DivideByZeroIndex); + return data->registerHandler(0, signal); } void SignalRegistrar::setCrashDumpDirectory(const char* crashDumpDirectory)