mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
sys.[ch]:
handle SIGFPE and allow the registered signal handler to do recovery rather than bail progs.h, pr_exec.c, pr_load.c: if pr_faultchecks is 1 (0 is default), handle division by 0 gracefully by loading the maximum representable number into the answer Closes: #58 the rest: kill the SIGFPE stuff
This commit is contained in:
parent
8cf5c9a430
commit
836c469737
10 changed files with 70 additions and 44 deletions
|
@ -249,6 +249,7 @@ extern struct cvar_s *pr_debug;
|
|||
extern struct cvar_s *pr_deadbeef_ents;
|
||||
extern struct cvar_s *pr_deadbeef_locals;
|
||||
extern struct cvar_s *pr_boundscheck;
|
||||
extern struct cvar_s *pr_faultchecks;
|
||||
|
||||
extern const char *pr_gametype;
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ int Sys_TimeID (void);
|
|||
// not to hog cpu when paused or debugging
|
||||
|
||||
void Sys_MaskFPUExceptions (void);
|
||||
void Sys_PushSignalHook (void (*hook)(int, void*), void *data);
|
||||
void Sys_PushSignalHook (int (*hook)(int, void*), void *data);
|
||||
void Sys_PopSignalHook (void);
|
||||
|
||||
// send text to the console
|
||||
|
|
|
@ -36,7 +36,7 @@ static const char rcsid[] =
|
|||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "QF/cvar.h"
|
||||
|
@ -168,13 +168,6 @@ PR_LeaveFunction (progs_t * pr)
|
|||
pr->pr_xstatement = pr->pr_stack[pr->pr_depth].s;
|
||||
}
|
||||
|
||||
static void
|
||||
signal_hook (int sig, void *data)
|
||||
{
|
||||
progs_t *pr = (progs_t *) data;
|
||||
PR_DumpState (pr);
|
||||
}
|
||||
|
||||
#define OPA (*op_a)
|
||||
#define OPB (*op_b)
|
||||
#define OPC (*op_c)
|
||||
|
@ -186,6 +179,42 @@ signal_hook (int sig, void *data)
|
|||
#define FNZ(x) ((x).integer_var && (x).integer_var != 0x80000000)
|
||||
|
||||
|
||||
static int
|
||||
signal_hook (int sig, void *data)
|
||||
{
|
||||
progs_t *pr = (progs_t *) data;
|
||||
|
||||
if (sig == SIGFPE && pr_faultchecks->int_val) {
|
||||
dstatement_t *st;
|
||||
pr_type_t *op_a, *op_b, *op_c;
|
||||
|
||||
st = pr->pr_statements + pr->pr_xstatement;
|
||||
op_a = pr->pr_globals + st->a;
|
||||
op_b = pr->pr_globals + st->b;
|
||||
op_c = pr->pr_globals + st->c;
|
||||
|
||||
switch (st->op) {
|
||||
case OP_DIV_F:
|
||||
if ((OPA.integer_var & 0x80000000)
|
||||
^ (OPB.integer_var & 0x80000000))
|
||||
OPC.integer_var = 0xff7fffff;
|
||||
else
|
||||
OPC.integer_var = 0x7f7fffff;
|
||||
return 1;
|
||||
case OP_DIV_I:
|
||||
if (OPA.integer_var & 0x80000000)
|
||||
OPC.integer_var = -0x80000000;
|
||||
else
|
||||
OPC.integer_var = 0x7fffffff;
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
PR_DumpState (pr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
PR_ExecuteProgram
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ static const char rcsid[] =
|
|||
|
||||
#include "compat.h"
|
||||
|
||||
cvar_t *pr_faultchecks;
|
||||
|
||||
static const char *
|
||||
function_get_key (void *f, void *_pr)
|
||||
{
|
||||
|
@ -294,6 +296,8 @@ PR_Init_Cvars (void)
|
|||
pr_deadbeef_locals = Cvar_Get ("pr_deadbeef_locals", "0", CVAR_NONE, NULL,
|
||||
"set to clear uninitialized local vars to "
|
||||
"0xdeadbeef");
|
||||
pr_faultchecks = Cvar_Get ("pr_faultchecks", "0", CVAR_NONE, NULL,
|
||||
"capture and handle division by 0 in progs");
|
||||
PR_Debug_Init_Cvars ();
|
||||
}
|
||||
|
||||
|
|
|
@ -583,17 +583,17 @@ static jmp_buf aiee_abort;
|
|||
|
||||
typedef struct sh_stack_s {
|
||||
struct sh_stack_s *next;
|
||||
void (*signal_hook)(int,void*);
|
||||
int (*signal_hook)(int,void*);
|
||||
void *data;
|
||||
} sh_stack_t;
|
||||
|
||||
static sh_stack_t *sh_stack;
|
||||
static sh_stack_t *free_sh;
|
||||
static void (*signal_hook)(int,void*);
|
||||
static int (*signal_hook)(int,void*);
|
||||
static void *signal_hook_data;
|
||||
|
||||
void
|
||||
Sys_PushSignalHook (void (*hook)(int, void *), void *data)
|
||||
Sys_PushSignalHook (int (*hook)(int, void *), void *data)
|
||||
{
|
||||
sh_stack_t *s;
|
||||
|
||||
|
@ -639,6 +639,8 @@ aiee (int sig)
|
|||
static void
|
||||
signal_handler (int sig)
|
||||
{
|
||||
int recover = 0;
|
||||
|
||||
printf ("Received signal %d, exiting...\n", sig);
|
||||
|
||||
switch (sig) {
|
||||
|
@ -660,21 +662,35 @@ signal_handler (int sig)
|
|||
#endif
|
||||
signal (SIGILL, aiee);
|
||||
signal (SIGSEGV, aiee);
|
||||
signal (SIGFPE, aiee);
|
||||
|
||||
if (!setjmp (aiee_abort)) {
|
||||
if (signal_hook)
|
||||
signal_hook (sig, signal_hook_data);
|
||||
recover = signal_hook (sig, signal_hook_data);
|
||||
Sys_Shutdown ();
|
||||
}
|
||||
|
||||
if (recover) {
|
||||
#ifndef _WIN32
|
||||
signal (SIGQUIT, SIG_DFL);
|
||||
signal (SIGTRAP, SIG_DFL);
|
||||
signal (SIGIOT, SIG_DFL);
|
||||
signal (SIGBUS, SIG_DFL);
|
||||
signal (SIGQUIT, signal_handler);
|
||||
signal (SIGTRAP, signal_handler);
|
||||
signal (SIGIOT, signal_handler);
|
||||
signal (SIGBUS, signal_handler);
|
||||
#endif
|
||||
signal (SIGILL, SIG_DFL);
|
||||
signal (SIGSEGV, SIG_DFL);
|
||||
signal (SIGILL, signal_handler);
|
||||
signal (SIGSEGV, signal_handler);
|
||||
signal (SIGFPE, signal_handler);
|
||||
} else {
|
||||
#ifndef _WIN32
|
||||
signal (SIGQUIT, SIG_DFL);
|
||||
signal (SIGTRAP, SIG_DFL);
|
||||
signal (SIGIOT, SIG_DFL);
|
||||
signal (SIGBUS, SIG_DFL);
|
||||
#endif
|
||||
signal (SIGILL, SIG_DFL);
|
||||
signal (SIGSEGV, SIG_DFL);
|
||||
signal (SIGFPE, SIG_DFL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -693,5 +709,5 @@ Sys_Init (void)
|
|||
signal (SIGILL, signal_handler);
|
||||
signal (SIGSEGV, signal_handler);
|
||||
signal (SIGTERM, signal_handler);
|
||||
// signal (SIGFPE, signal_handler);
|
||||
signal (SIGFPE, signal_handler);
|
||||
}
|
||||
|
|
|
@ -95,8 +95,6 @@ startup (void)
|
|||
Sys_Error ("This version of " PROGRAM
|
||||
" requires at least Win95 or NT 4.0");
|
||||
}
|
||||
#else
|
||||
signal (SIGFPE, SIG_IGN);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -69,21 +69,12 @@ shutdown (void)
|
|||
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
void
|
||||
floating_point_exception_handler (int whatever)
|
||||
{
|
||||
// Sys_Warn("floating point exception\n");
|
||||
signal (SIGFPE, floating_point_exception_handler);
|
||||
}
|
||||
|
||||
int
|
||||
main (int c, const char *v[])
|
||||
{
|
||||
|
||||
double time, oldtime, newtime;
|
||||
|
||||
signal (SIGFPE, SIG_IGN);
|
||||
|
||||
memset (&host_parms, 0, sizeof (host_parms));
|
||||
|
||||
COM_InitArgv (c, v);
|
||||
|
|
|
@ -80,8 +80,6 @@ main (int argc, const char **argv)
|
|||
{
|
||||
double time, oldtime, newtime;
|
||||
|
||||
signal (SIGFPE, SIG_IGN);
|
||||
|
||||
memset (&host_parms, 0, sizeof (host_parms));
|
||||
|
||||
COM_InitArgv (argc, argv);
|
||||
|
|
|
@ -96,8 +96,6 @@ startup (void)
|
|||
Sys_Error ("This version of " PROGRAM
|
||||
" requires at least Win95 or NT 4.0");
|
||||
}
|
||||
#else
|
||||
signal (SIGFPE, SIG_IGN);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -70,12 +70,6 @@ shutdown (void)
|
|||
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
void
|
||||
floating_point_exception_handler (int whatever)
|
||||
{
|
||||
signal (SIGFPE, floating_point_exception_handler);
|
||||
}
|
||||
|
||||
int skipframes;
|
||||
|
||||
int
|
||||
|
@ -84,9 +78,6 @@ main (int c, const char *v[])
|
|||
// static char cwd[1024];
|
||||
double time, oldtime, newtime;
|
||||
|
||||
// signal(SIGFPE, floating_point_exception_handler);
|
||||
signal (SIGFPE, SIG_IGN);
|
||||
|
||||
memset (&host_parms, 0, sizeof (host_parms));
|
||||
|
||||
COM_InitArgv (c, v);
|
||||
|
|
Loading…
Reference in a new issue