/* Support for handling exceptions in Dylan (other than MM traps) */
/* Currently, we just handle stack overflows arithmetic exceptions */
/* ---*** TODO: Find out how to trap stack overflows on Linux */
extern int inside_dylan_ffi_barrier();
extern void dylan_stack_overflow_handler(PVOID base_address, int size, DWORD protection);
extern void dylan_integer_overflow_handler();
extern void dylan_integer_divide_0_handler();
extern void dylan_float_divide_0_handler();
extern void dylan_float_overflow_handler();
extern void dylan_float_underflow_handler();
/* Linux exception handling: Setup a signal handler for SIGFPE (floating point exceptions)
using the SA_SIGINFO extension to sigaction. Use of this flag passes two extra arguments
to the signal handler. One of those arguments is a siginfo structure which contains
details on the exception. In particular, it classifies the exception (e.g., integer
overflow, float overflow, etc.) We use this classification to invoke the appropriate
Dylan handler */
/* ---*** TODO: Find out how to trap stack overflows and add an appropriate handler */
#define EXCEPTION_PREAMBLE() \
struct sigaction oldFPEHandler; \
void doFPEHandler (int signum, siginfo_t * si, void * p) { \
DylanFPEHandler(oldFPEHandler.sa_handler, signum, si, p); \
} \
oldFPEHandler.sa_handler = (__sighandler_t)doFPEHandler; \
EstablishDylanExceptionHandlers(&oldFPEHandler); \
{
#define EXCEPTION_POSTAMBLE() \
} \
RemoveDylanExceptionHandlers(&oldFPEHandler);
typedef void (* SIG_SIGINFO)(int, siginfo_t *, void *);
static void DylanFPEHandler (__sighandler_t, int, siginfo_t *, void *);
static void EstablishDylanExceptionHandlers (struct sigaction * oldFPEHandler)
{
struct sigaction newFPEHandler;
newFPEHandler.sa_handler = oldFPEHandler->sa_handler;
sigemptyset(&newFPEHandler.sa_mask);
newFPEHandler.sa_flags = SA_SIGINFO;
sigaction(SIGFPE, &newFPEHandler, oldFPEHandler);
}
static void RemoveDylanExceptionHandlers (struct sigaction * oldFPEHandler)
{
sigaction(SIGFPE, oldFPEHandler, NULL);
}
static void DylanFPEHandler (__sighandler_t oldHandler, int signum, siginfo_t * si, void * p)
{
if (inside_dylan_ffi_barrier() == 0) { }
else {
switch (si->si_code) {
case FPE_INTDIV:
dylan_integer_divide_0_handler();
break;
case FPE_INTOVF:
dylan_integer_overflow_handler();
break;
case FPE_FLTDIV:
dylan_float_divide_0_handler();
break;
case FPE_FLTOVF:
dylan_float_overflow_handler();
break;
case FPE_FLTUND:
dylan_float_underflow_handler();
break;
default:
break;
}
}
// Here iff we should invoke the previous handler ...
if (oldHandler == SIG_DFL) {
signal(signum, SIG_DFL);
raise(signum);
}
else
// ---*** NOTE: What if the old handler isn't expecting this calling sequence?
(*(SIG_SIGINFO)oldHandler)(signum, si, p);
return;
}
syntax highlighted by Code2HTML, v. 0.9.1