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;
};
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.

View File

@ -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(&divideByZeroHandler));
expect(t, signals.registerHandler(SignalRegistrar::DivideByZero, &divideByZeroHandler));
}
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)) {
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*)

View File

@ -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)