refactor SignalRegistrar interface

This commit is contained in:
Joshua Warner 2014-02-21 23:23:01 -07:00
parent ca7d51edb3
commit bc9f7d2f87
4 changed files with 62 additions and 31 deletions

View File

@ -36,21 +36,29 @@ class SignalRegistrar {
void** thread) = 0; void** thread) = 0;
}; };
enum Signal {
// "Segmentation fault" exceptions (mostly null pointer dereference, but
// generally access to any non-mapped memory)
SegFault,
DivideByZero,
};
SignalRegistrar(); SignalRegistrar();
~SignalRegistrar(); ~SignalRegistrar();
// Register a handler for segfault signals. // Register a handler for the given signal.
// After this method call, any segfault exceptions (mostly null pointer // After this method call, anytime the given signal is raised, it will be
// dereference, but generally access to any non-mapped memory) will be handled // handled by the given handler.
// by the given handler. Pass null (0) to unregister a handler.
// Returns true upon success, false upon failure // 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. // Unregister a handler for the given signal.
// After this method call, any divide-by-zero exceptions will be handled by // After this method call, the given signal will no longer be handled (or,
// the given handler. Pass null (0) to unregister a handler. // rather, it go back to being handled by whatever was registered to handle it
// before us).
// Returns true upon success, false upon failure // 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 // Set the directory that a crash dump will be written to should an unhandled
// exception be thrown. // exception be thrown.

View File

@ -8930,8 +8930,8 @@ class MyProcessor: public Processor {
compilationHandlers->dispose(allocator); compilationHandlers->dispose(allocator);
signals.handleSegFault(0); signals.unregisterHandler(SignalRegistrar::SegFault);
signals.handleDivideByZero(0); signals.unregisterHandler(SignalRegistrar::DivideByZero);
signals.setCrashDumpDirectory(0); signals.setCrashDumpDirectory(0);
allocator->free(this, sizeof(*this)); allocator->free(this, sizeof(*this));
@ -9124,10 +9124,10 @@ class MyProcessor: public Processor {
#endif #endif
segFaultHandler.m = t->m; segFaultHandler.m = t->m;
expect(t, signals.handleSegFault(&segFaultHandler)); expect(t, signals.registerHandler(SignalRegistrar::SegFault, &segFaultHandler));
divideByZeroHandler.m = t->m; divideByZeroHandler.m = t->m;
expect(t, signals.handleDivideByZero(&divideByZeroHandler)); expect(t, signals.registerHandler(SignalRegistrar::DivideByZero, &divideByZeroHandler));
} }
virtual void callWithCurrentContinuation(Thread* t, object receiver) { virtual void callWithCurrentContinuation(Thread* t, object receiver) {

View File

@ -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)) { switch(signal) {
return false; case SegFault:
} if(!data->registerHandler(handler, posix::SegFaultSignalIndex)) {
if (posix::AltSegFaultSignal != posix::InvalidSignal) { return false;
return data->registerHandler(handler, posix::AltSegFaultSignalIndex); }
} else { if (posix::AltSegFaultSignal != posix::InvalidSignal) {
return true; 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*) void SignalRegistrar::setCrashDumpDirectory(const char*)

View File

@ -36,8 +36,6 @@ namespace avian {
namespace system { namespace system {
namespace windows { namespace windows {
const unsigned SegFaultIndex = 0;
const unsigned DivideByZeroIndex = 1;
const unsigned HandlerCount = 2; const unsigned HandlerCount = 2;
@ -161,10 +159,10 @@ LONG CALLBACK handleException(LPEXCEPTION_POINTERS e)
{ {
SignalRegistrar::Handler* handler = 0; SignalRegistrar::Handler* handler = 0;
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { 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 } else if (e->ExceptionRecord->ExceptionCode
== EXCEPTION_INT_DIVIDE_BY_ZERO) { == EXCEPTION_INT_DIVIDE_BY_ZERO) {
handler = SignalRegistrar::Data::instance->handlers[DivideByZeroIndex]; handler = SignalRegistrar::Data::instance->handlers[SignalRegistrar::DivideByZero];
} }
if (handler) { if (handler) {
@ -219,6 +217,10 @@ SignalRegistrar::~SignalRegistrar()
bool SignalRegistrar::Data::registerHandler(Handler* handler, int index) bool SignalRegistrar::Data::registerHandler(Handler* handler, int index)
{ {
if(index != SegFault && index != DivideByZero) {
crash();
}
if (handler) { if (handler) {
handlers[index] = handler; handlers[index] = handler;
@ -271,14 +273,14 @@ NO_RETURN void crash()
abort(); 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) void SignalRegistrar::setCrashDumpDirectory(const char* crashDumpDirectory)