/*
* 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 <windows.h>
#include <exceptions.h> /* 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
syntax highlighted by Code2HTML, v. 0.9.1