This commit is contained in:
Vitor Santos Costa 2016-07-31 09:54:43 -05:00
parent 5f2964cce6
commit 9b3bbf5e33

309
os/sig.c
View File

@ -1,6 +1,7 @@
#include "sysbits.h"
#if HAVE_SIGINFO_H
#include <siginfo.h>
#endif
@ -12,40 +13,26 @@
#include <fpu_control.h>
#endif
#if HAVE_SIGNAL
#ifdef MSH
#define SIGFPE SIGDIV
#endif
static void HandleMatherr(int sig, void *sipv, void *uapv);
#define PLSIG_PREPARED 0x01 /* signal is prepared */
#define PLSIG_THROW 0x02 /* throw signal(num, name) */
#define PLSIG_SYNC 0x04 /* call synchronously */
#define PLSIG_NOFRAME 0x08 /* Do not create a Prolog frame */
#define SIG_PROLOG_OFFSET 32 /* Start of Prolog signals */
#define SIG_EXCEPTION (SIG_PROLOG_OFFSET+0)
#ifdef ATOMGC
#ifdef O_ATOMGC
#define SIG_ATOM_GC (SIG_PROLOG_OFFSET+1)
#endif
#define SIG_GC (SIG_PROLOG_OFFSET+2)
#ifdef THREADS
#define SIG_THREAD_SIGNAL (SIG_PROLOG_OFFSET + 3)b
#ifdef O_PLMT
#define SIG_THREAD_SIGNAL (SIG_PROLOG_OFFSET+3)
#endif
#define SIG_FREECLAUSES (SIG_PROLOG_OFFSET+4)
#define SIG_PLABORT (SIG_PROLOG_OFFSET+5)
static struct signame {
int sig;
static struct signame
{ int sig;
const char *name;
int flags;
} signames[] = {
} signames[] =
{
#ifdef SIGHUP
{ SIGHUP, "hup", 0},
#endif
@ -55,9 +42,7 @@ static struct signame {
#endif
{ SIGILL, "ill", 0},
{ SIGABRT, "abrt", 0},
#if HAVE_SIGFPE
{SIGFPE, "fpe", PLSIG_THROW},
#endif
{ SIGFPE, "fpe", 0},
#ifdef SIGKILL
{ SIGKILL, "kill", 0},
#endif
@ -66,7 +51,7 @@ static struct signame {
{ SIGPIPE, "pipe", 0},
#endif
#ifdef SIGALRM
{SIGALRM, "alrm", PLSIG_THROW},
{ SIGALRM, "alrm", 0},
#endif
{ SIGTERM, "term", 0},
#ifdef SIGUSR1
@ -112,13 +97,13 @@ static struct signame {
{ SIGPOLL, "poll", 0},
#endif
#ifdef SIGXCPU
{SIGXCPU, "xcpu", PLSIG_THROW},
{ SIGXCPU, "xcpu", 0},
#endif
#ifdef SIGXFSZ
{SIGXFSZ, "xfsz", PLSIG_THROW},
{ SIGXFSZ, "xfsz", 0},
#endif
#ifdef SIGVTALRM
{SIGVTALRM, "vtalrm", PLSIG_THROW},
{ SIGVTALRM, "vtalrm", 0},
#endif
#ifdef SIGPROF
{ SIGPROF, "prof", 0},
@ -137,7 +122,6 @@ static struct signame {
{-1, NULL, 0}};
typedef void (*signal_handler_t)(int, void *, void *);
#if HAVE_SIGACTION
static void my_signal_info(int sig, void *handler) {
@ -161,15 +145,30 @@ static void my_signal(int sig, void *handler) {
#else
static void my_signal(int sig, void *handler) { signal(sig, handler); }
static void my_signal(int sig, void *handler) {
#if HAVE_SIGNAL
signal(sig, handler);
#endif
}
static void my_signal_info(int sig, void *handler) {
#if HAVE_SIGNAL
if (signal(sig, (void *)handler) == SIG_ERR)
exit(1);
#endif
}
#endif
static void HandleMatherr(int sig, void *sipv, void *uapv) {
CACHE_REGS
LOCAL_matherror = Yap_MathException();
/* reset the registers so that we don't have trash in abstract machine */
Yap_external_signal(worker_id, YAP_FPE_SIGNAL);
}
/* SWI emulation */
int Yap_signal_index(const char *name) {
struct signame *sn = signames;
@ -244,8 +243,6 @@ static void HandleSIGSEGV(int sig, void *sipv, void *uap) {
}
#endif /* SIGSEGV */
#if HAVE_SIGFPE
/* by default Linux with glibc is IEEE compliant anyway..., but we will pretend
* it is not. */
static bool set_fpu_exceptions(Term flag) {
@ -321,99 +318,11 @@ static bool set_fpu_exceptions(Term flag) {
return true;
}
bool Yap_set_fpu_exceptions(Term flag) { return set_fpu_exceptions(flag); }
yap_error_number Yap_MathException__(USES_REGS1) {
#if HAVE_FETESTEXCEPT
int raised;
#if !defined(LIGHT) && !_MSC_VER && !defined(__MINGW32__)
// #pragma STDC FENV_ACCESS ON
if ((raised = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW))) {
feclearexcept(FE_ALL_EXCEPT);
if (raised & FE_OVERFLOW) {
return EVALUATION_ERROR_FLOAT_OVERFLOW;
} else if (raised & FE_DIVBYZERO) {
return EVALUATION_ERROR_ZERO_DIVISOR;
} else if (raised & FE_UNDERFLOW) {
return EVALUATION_ERROR_FLOAT_UNDERFLOW;
//} else if (raised & (FE_INVALID|FE_INEXACT)) {
// return EVALUATION_ERROR_UNDEFINED;
} else {
return EVALUATION_ERROR_UNDEFINED;
}
}
#elif _WIN32
unsigned int raised;
int err;
// Show original FP control word and do calculation.
err = _controlfp_s(&raised, 0, 0);
if (err) {
return EVALUATION_ERROR_UNDEFINED;
}
if (raised) {
feclearexcept(FE_ALL_EXCEPT);
if (raised & FE_OVERFLOW) {
return EVALUATION_ERROR_FLOAT_OVERFLOW;
} else if (raised & FE_DIVBYZERO) {
return EVALUATION_ERROR_ZERO_DIVISOR;
} else if (raised & FE_UNDERFLOW) {
return EVALUATION_ERROR_FLOAT_UNDERFLOW;
//} else if (raised & (FE_INVALID|FE_INEXACT)) {
// return EVALUATION_ERROR_UNDEFINED;
} else {
return EVALUATION_ERROR_UNDEFINED;
}
}
#elif (defined(__svr4__) || defined(__SVR4))
switch (sip->si_code) {
case FPE_INTDIV:
return EVALUATION_ERROR_ZERO_DIVISOR;
break;
case FPE_INTOVF:
return EVALUATION_ERROR_INT_OVERFLOW;
break;
case FPE_FLTDIV:
return EVALUATION_ERROR_ZERO_DIVISOR;
break;
case FPE_FLTOVF:
return EVALUATION_ERROR_FLOAT_OVERFLOW;
break;
case FPE_FLTUND:
return EVALUATION_ERROR_FLOAT_UNDERFLOW;
break;
case FPE_FLTRES:
case FPE_FLTINV:
case FPE_FLTSUB:
default:
return EVALUATION_ERROR_UNDEFINED;
}
set_fpu_exceptions(0);
#endif
return LOCAL_matherror;
}
static Int fpe_error(USES_REGS1) {
Yap_Error(LOCAL_matherror, LOCAL_mathtt, LOCAL_mathstring);
LOCAL_matherror = YAP_NO_ERROR;
LOCAL_mathtt = TermNil;
LOCAL_mathstring = NULL;
return FALSE;
}
static void HandleMatherr(int sig, void *sipv, void *uapv) {
CACHE_REGS
LOCAL_matherror = Yap_MathException();
/* reset the registers so that we don't have trash in abstract machine */
Yap_external_signal(worker_id, YAP_FPE_SIGNAL);
}
#endif /* SIGFPE */
#if !defined(LIGHT) && !_MSC_VER && !defined(__MINGW32__) && !defined(LIGHT)
static RETSIGTYPE ReceiveSignal(int s, void *x, void *y) {
static void * ReceiveSignal(int s, void *x, void *y) {
CACHE_REGS
LOCAL_PrologMode |= InterruptMode;
my_signal(s, ReceiveSignal);
@ -503,40 +412,6 @@ static BOOL WINAPI MSCHandleSignal(DWORD dwCtrlType) {
}
#endif
/* SIGINT can cause problems, if caught before full initialization */
void Yap_InitOSSignals(int wid) {
if (GLOBAL_PrologShouldHandleInterrupts) {
#if !defined(LIGHT) && !_MSC_VER && !defined(__MINGW32__) && !defined(LIGHT)
my_signal(SIGQUIT, ReceiveSignal);
my_signal(SIGKILL, ReceiveSignal);
my_signal(SIGUSR1, ReceiveSignal);
my_signal(SIGUSR2, ReceiveSignal);
my_signal(SIGHUP, ReceiveSignal);
my_signal(SIGALRM, ReceiveSignal);
my_signal(SIGVTALRM, ReceiveSignal);
#endif
#ifdef SIGPIPE
my_signal(SIGPIPE, ReceiveSignal);
#endif
#if _MSC_VER || defined(__MINGW32__)
signal(SIGINT, SIG_IGN);
SetConsoleCtrlHandler(MSCHandleSignal, TRUE);
#else
my_signal(SIGINT, ReceiveSignal);
#endif
#ifdef HAVE_SIGFPE
my_signal(SIGFPE, HandleMatherr);
#endif
#if HAVE_SIGSEGV
my_signal_info(SIGSEGV, HandleSIGSEGV);
#endif
#ifdef YAPOR_COW
signal(SIGCHLD, SIG_IGN); /* avoid ghosts */
#endif
}
}
#endif /* HAVE_SIGNAL */
/* wrapper for alarm system call */
#if _MSC_VER || defined(__MINGW32__)
@ -877,6 +752,126 @@ void rw_lock_voodoo(void) {
#endif /* YAPOR || THREADS */
yap_error_number Yap_MathException__(USES_REGS1) {
#if HAVE_FETESTEXCEPT
int raised;
// #pragma STDC FENV_ACCESS ON
if ((raised = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW))) {
feclearexcept(FE_ALL_EXCEPT);
if (raised & FE_OVERFLOW) {
return EVALUATION_ERROR_FLOAT_OVERFLOW;
} else if (raised & FE_DIVBYZERO) {
return EVALUATION_ERROR_ZERO_DIVISOR;
} else if (raised & FE_UNDERFLOW) {
return EVALUATION_ERROR_FLOAT_UNDERFLOW;
//} else if (raised & (FE_INVALID|FE_INEXACT)) {
// return EVALUATION_ERROR_UNDEFINED;
} else {
return EVALUATION_ERROR_UNDEFINED;
}
}
#elif _WIN32
unsigned int raised;
int err;
// Show original FP control word and do calculation.
err = _controlfp_s(&raised, 0, 0);
if (err) {
return EVALUATION_ERROR_UNDEFINED;
}
if (raised) {
feclearexcept(FE_ALL_EXCEPT);
if (raised & FE_OVERFLOW) {
return EVALUATION_ERROR_FLOAT_OVERFLOW;
} else if (raised & FE_DIVBYZERO) {
return EVALUATION_ERROR_ZERO_DIVISOR;
} else if (raised & FE_UNDERFLOW) {
return EVALUATION_ERROR_FLOAT_UNDERFLOW;
//} else if (raised & (FE_INVALID|FE_INEXACT)) {
// return EVALUATION_ERROR_UNDEFINED;
} else {
return EVALUATION_ERROR_UNDEFINED;
}
}
#elif (defined(__svr4__) || defined(__SVR4))
switch (sip->si_code) {
case FPE_INTDIV:
return EVALUATION_ERROR_ZERO_DIVISOR;
break;
case FPE_INTOVF:
return EVALUATION_ERROR_INT_OVERFLOW;
break;
case FPE_FLTDIV:
return EVALUATION_ERROR_ZERO_DIVISOR;
break;
case FPE_FLTOVF:
return EVALUATION_ERROR_FLOAT_OVERFLOW;
break;
case FPE_FLTUND:
return EVALUATION_ERROR_FLOAT_UNDERFLOW;
break;
case FPE_FLTRES:
case FPE_FLTINV:
case FPE_FLTSUB:
default:
return EVALUATION_ERROR_UNDEFINED;
}
set_fpu_exceptions(0);
#endif
return LOCAL_matherror;
}
static Int fpe_error(USES_REGS1) {
Yap_Error(LOCAL_matherror, LOCAL_mathtt, LOCAL_mathstring);
LOCAL_matherror = YAP_NO_ERROR;
LOCAL_mathtt = TermNil;
LOCAL_mathstring = NULL;
return FALSE;
}
/* SIGINT can cause problems, if caught before full initialization */
void Yap_InitOSSignals(int wid) {
if (GLOBAL_PrologShouldHandleInterrupts) {
#if !defined(LIGHT) && !_MSC_VER && !defined(__MINGW32__) && !defined(LIGHT)
my_signal(SIGQUIT, ReceiveSignal);
my_signal(SIGKILL, ReceiveSignal);
my_signal(SIGUSR1, ReceiveSignal);
my_signal(SIGUSR2, ReceiveSignal);
my_signal(SIGHUP, ReceiveSignal);
my_signal(SIGALRM, ReceiveSignal);
my_signal(SIGVTALRM, ReceiveSignal);
#endif
#ifdef SIGPIPE
my_signal(SIGPIPE, ReceiveSignal);
#endif
#if _MSC_VER || defined(__MINGW32__)
signal(SIGINT, SIG_IGN);
SetConsoleCtrlHandler(MSCHandleSignal, TRUE);
#else
my_signal(SIGINT, ReceiveSignal);
#endif
#ifdef HAVE_SIGFPE
my_signal(SIGFPE, HandleMatherr);
#endif
#if HAVE_SIGSEGV
my_signal_info(SIGSEGV, HandleSIGSEGV);
#endif
#ifdef YAPOR_COW
signal(SIGCHLD, SIG_IGN); /* avoid ghosts */
#endif
}
}
bool Yap_set_fpu_exceptions(Term flag) {
return set_fpu_exceptions(flag);
}
void Yap_InitSignalPreds(void) {
CACHE_REGS
Term cm = CurrentModule;