mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-05-31 08:41:11 +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_ents;
|
||||||
extern struct cvar_s *pr_deadbeef_locals;
|
extern struct cvar_s *pr_deadbeef_locals;
|
||||||
extern struct cvar_s *pr_boundscheck;
|
extern struct cvar_s *pr_boundscheck;
|
||||||
|
extern struct cvar_s *pr_faultchecks;
|
||||||
|
|
||||||
extern const char *pr_gametype;
|
extern const char *pr_gametype;
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ int Sys_TimeID (void);
|
||||||
// not to hog cpu when paused or debugging
|
// not to hog cpu when paused or debugging
|
||||||
|
|
||||||
void Sys_MaskFPUExceptions (void);
|
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);
|
void Sys_PopSignalHook (void);
|
||||||
|
|
||||||
// send text to the console
|
// send text to the console
|
||||||
|
|
|
@ -36,7 +36,7 @@ static const char rcsid[] =
|
||||||
#ifdef HAVE_STRINGS_H
|
#ifdef HAVE_STRINGS_H
|
||||||
# include <strings.h>
|
# include <strings.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "QF/cvar.h"
|
#include "QF/cvar.h"
|
||||||
|
@ -168,13 +168,6 @@ PR_LeaveFunction (progs_t * pr)
|
||||||
pr->pr_xstatement = pr->pr_stack[pr->pr_depth].s;
|
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 OPA (*op_a)
|
||||||
#define OPB (*op_b)
|
#define OPB (*op_b)
|
||||||
#define OPC (*op_c)
|
#define OPC (*op_c)
|
||||||
|
@ -186,6 +179,42 @@ signal_hook (int sig, void *data)
|
||||||
#define FNZ(x) ((x).integer_var && (x).integer_var != 0x80000000)
|
#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
|
PR_ExecuteProgram
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,8 @@ static const char rcsid[] =
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
|
cvar_t *pr_faultchecks;
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
function_get_key (void *f, void *_pr)
|
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,
|
pr_deadbeef_locals = Cvar_Get ("pr_deadbeef_locals", "0", CVAR_NONE, NULL,
|
||||||
"set to clear uninitialized local vars to "
|
"set to clear uninitialized local vars to "
|
||||||
"0xdeadbeef");
|
"0xdeadbeef");
|
||||||
|
pr_faultchecks = Cvar_Get ("pr_faultchecks", "0", CVAR_NONE, NULL,
|
||||||
|
"capture and handle division by 0 in progs");
|
||||||
PR_Debug_Init_Cvars ();
|
PR_Debug_Init_Cvars ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -583,17 +583,17 @@ static jmp_buf aiee_abort;
|
||||||
|
|
||||||
typedef struct sh_stack_s {
|
typedef struct sh_stack_s {
|
||||||
struct sh_stack_s *next;
|
struct sh_stack_s *next;
|
||||||
void (*signal_hook)(int,void*);
|
int (*signal_hook)(int,void*);
|
||||||
void *data;
|
void *data;
|
||||||
} sh_stack_t;
|
} sh_stack_t;
|
||||||
|
|
||||||
static sh_stack_t *sh_stack;
|
static sh_stack_t *sh_stack;
|
||||||
static sh_stack_t *free_sh;
|
static sh_stack_t *free_sh;
|
||||||
static void (*signal_hook)(int,void*);
|
static int (*signal_hook)(int,void*);
|
||||||
static void *signal_hook_data;
|
static void *signal_hook_data;
|
||||||
|
|
||||||
void
|
void
|
||||||
Sys_PushSignalHook (void (*hook)(int, void *), void *data)
|
Sys_PushSignalHook (int (*hook)(int, void *), void *data)
|
||||||
{
|
{
|
||||||
sh_stack_t *s;
|
sh_stack_t *s;
|
||||||
|
|
||||||
|
@ -639,6 +639,8 @@ aiee (int sig)
|
||||||
static void
|
static void
|
||||||
signal_handler (int sig)
|
signal_handler (int sig)
|
||||||
{
|
{
|
||||||
|
int recover = 0;
|
||||||
|
|
||||||
printf ("Received signal %d, exiting...\n", sig);
|
printf ("Received signal %d, exiting...\n", sig);
|
||||||
|
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
|
@ -660,21 +662,35 @@ signal_handler (int sig)
|
||||||
#endif
|
#endif
|
||||||
signal (SIGILL, aiee);
|
signal (SIGILL, aiee);
|
||||||
signal (SIGSEGV, aiee);
|
signal (SIGSEGV, aiee);
|
||||||
|
signal (SIGFPE, aiee);
|
||||||
|
|
||||||
if (!setjmp (aiee_abort)) {
|
if (!setjmp (aiee_abort)) {
|
||||||
if (signal_hook)
|
if (signal_hook)
|
||||||
signal_hook (sig, signal_hook_data);
|
recover = signal_hook (sig, signal_hook_data);
|
||||||
Sys_Shutdown ();
|
Sys_Shutdown ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (recover) {
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
signal (SIGQUIT, SIG_DFL);
|
signal (SIGQUIT, signal_handler);
|
||||||
signal (SIGTRAP, SIG_DFL);
|
signal (SIGTRAP, signal_handler);
|
||||||
signal (SIGIOT, SIG_DFL);
|
signal (SIGIOT, signal_handler);
|
||||||
signal (SIGBUS, SIG_DFL);
|
signal (SIGBUS, signal_handler);
|
||||||
#endif
|
#endif
|
||||||
signal (SIGILL, SIG_DFL);
|
signal (SIGILL, signal_handler);
|
||||||
signal (SIGSEGV, SIG_DFL);
|
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 (SIGILL, signal_handler);
|
||||||
signal (SIGSEGV, signal_handler);
|
signal (SIGSEGV, signal_handler);
|
||||||
signal (SIGTERM, 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
|
Sys_Error ("This version of " PROGRAM
|
||||||
" requires at least Win95 or NT 4.0");
|
" requires at least Win95 or NT 4.0");
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
signal (SIGFPE, SIG_IGN);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,21 +69,12 @@ shutdown (void)
|
||||||
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK);
|
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
|
int
|
||||||
main (int c, const char *v[])
|
main (int c, const char *v[])
|
||||||
{
|
{
|
||||||
|
|
||||||
double time, oldtime, newtime;
|
double time, oldtime, newtime;
|
||||||
|
|
||||||
signal (SIGFPE, SIG_IGN);
|
|
||||||
|
|
||||||
memset (&host_parms, 0, sizeof (host_parms));
|
memset (&host_parms, 0, sizeof (host_parms));
|
||||||
|
|
||||||
COM_InitArgv (c, v);
|
COM_InitArgv (c, v);
|
||||||
|
|
|
@ -80,8 +80,6 @@ main (int argc, const char **argv)
|
||||||
{
|
{
|
||||||
double time, oldtime, newtime;
|
double time, oldtime, newtime;
|
||||||
|
|
||||||
signal (SIGFPE, SIG_IGN);
|
|
||||||
|
|
||||||
memset (&host_parms, 0, sizeof (host_parms));
|
memset (&host_parms, 0, sizeof (host_parms));
|
||||||
|
|
||||||
COM_InitArgv (argc, argv);
|
COM_InitArgv (argc, argv);
|
||||||
|
|
|
@ -96,8 +96,6 @@ startup (void)
|
||||||
Sys_Error ("This version of " PROGRAM
|
Sys_Error ("This version of " PROGRAM
|
||||||
" requires at least Win95 or NT 4.0");
|
" requires at least Win95 or NT 4.0");
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
signal (SIGFPE, SIG_IGN);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,12 +70,6 @@ shutdown (void)
|
||||||
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK);
|
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 skipframes;
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -84,9 +78,6 @@ main (int c, const char *v[])
|
||||||
// static char cwd[1024];
|
// static char cwd[1024];
|
||||||
double time, oldtime, newtime;
|
double time, oldtime, newtime;
|
||||||
|
|
||||||
// signal(SIGFPE, floating_point_exception_handler);
|
|
||||||
signal (SIGFPE, SIG_IGN);
|
|
||||||
|
|
||||||
memset (&host_parms, 0, sizeof (host_parms));
|
memset (&host_parms, 0, sizeof (host_parms));
|
||||||
|
|
||||||
COM_InitArgv (c, v);
|
COM_InitArgv (c, v);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue