/* * Special signal handling for cygwin on Windows. * * Even though cygwin behaves like "unix", its signal handling mechanism * is crippled. I haven't been able to get/set the EIP addresses from * the siginfo_t and related data structures. So here I'm using * Windows and some gcc assembly hacks to get things done. */ #if defined(__i386__) && defined(__CYGWIN32__) && defined(__GNUC__) #include "ml-unixdep.h" #include "signal-sysdep.h" #include "ml-base.h" #include "vproc-state.h" #include "ml-state.h" #include "ml-globals.h" #include #include /* Cygwin stuff */ #define SELF_VPROC (VProc[0]) /* generic handler for cygwin "signals" such as interrupt, alarm */ /* returns TRUE if the main thread is running ML code */ BOOL cygwin_generic_handler(int code) { vproc_state_t *vsp = SELF_VPROC; vsp->vp_sigCounts[code].nReceived++; vsp->vp_totalSigCount.nReceived++; vsp->vp_limitPtrMask = 0; if (vsp->vp_inMLFlag && (! vsp->vp_handlerPending) && (! vsp->vp_inSigHandler)) { vsp->vp_handlerPending = TRUE; SIG_ZeroLimitPtr(); return TRUE; } return FALSE; } PVT BOOL __stdcall ctrl_c_handler(DWORD type) { switch (type) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: if (cygwin_generic_handler(SIGINT)) { return TRUE; } return FALSE; default: return FALSE; } } void InitFaultHandlers(ml_state_t * msp) { /* Install the control-C handler */ if (! SetConsoleCtrlHandler(ctrl_c_handler, TRUE)) { Die("cygwin:InitFaultHandlers: can't install ctrl-c-handler\n"); } /* Initialize the floating-point unit */ SIG_InitFPE (); } /* * This filter catches all exceptions. */ PVT int page_fault_handler (EXCEPTION_RECORD * exn, void * foo, CONTEXT * c, void * bar) { extern Word_t request_fault[]; ml_state_t * msp = SELF_VPROC->vp_state; int code = exn->ExceptionCode; DWORD pc = (DWORD)exn->ExceptionAddress; if (! SELF_VPROC->vp_inMLFlag) { Die("cygwin:fault_handler: bogus fault not in ML: %#x\n", code); } switch (code) { case EXCEPTION_INT_DIVIDE_BY_ZERO: /* Say("Divide by zero at %p\n", pc); */ msp->ml_faultExn = DivId; msp->ml_faultPC = pc; c->Eip = (DWORD)request_fault; break; case EXCEPTION_INT_OVERFLOW: /* Say("Overflow at %p\n", pc); */ msp->ml_faultExn = OverflowId; msp->ml_faultPC = pc; c->Eip = (DWORD)request_fault; break; default: Die("cygwin:fault_handler: unexpected fault @%#x, code=%#x", pc, code); } return FALSE; } asm (".equ __win32_exception_list,0"); extern exception_list * _win32_exception_list asm ("%fs:__win32_exception_list"); /* * This overrides the default RunML. * It just adds a new exception handler at the very beginning before * ML is executed. */ void RunML(ml_state_t * msp) { extern void SystemRunML(ml_state_t *); exception_list el; el.handler = page_fault_handler; el.prev = _win32_exception_list; _win32_exception_list = ⪙ return SystemRunML(msp); } #endif