mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-17 22:50:51 +00:00
Move the signal handling code from video/targets/* to sys.c (I'm leaving
the SDL target files for Despair since he's working on the currently). Also make progs segfault handling much more robust (and general: sigill etc too:)
This commit is contained in:
parent
118e982edd
commit
5009213564
12 changed files with 137 additions and 171 deletions
|
@ -70,7 +70,9 @@ int Sys_TimeID (void);
|
|||
// called to yield for a little bit so as
|
||||
// not to hog cpu when paused or debugging
|
||||
|
||||
void Sys_MaskExceptions (void);
|
||||
void Sys_MaskFPUExceptions (void);
|
||||
void Sys_PushSignalHook (void (*hook)(int, void*), void *data);
|
||||
void Sys_PopSignalHook (void);
|
||||
|
||||
// send text to the console
|
||||
|
||||
|
|
|
@ -268,6 +268,13 @@ PR_LeaveFunction (progs_t * pr)
|
|||
return 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)
|
||||
|
@ -311,6 +318,8 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
st = &pr->pr_statements[PR_EnterFunction (pr, f)];
|
||||
startprofile = profile = 0;
|
||||
|
||||
Sys_PushSignalHook (signal_hook, pr);
|
||||
|
||||
while (1) {
|
||||
pr_type_t *op_a, *op_b, *op_c;
|
||||
|
||||
|
@ -511,13 +520,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to address an out of "
|
||||
"bounds edict");
|
||||
return;
|
||||
}
|
||||
if (pr_boundscheck->int_val
|
||||
&& (OPA.entity_var == 0 && pr->null_bad)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "assignment to world entity");
|
||||
return;
|
||||
}
|
||||
if (pr_boundscheck->int_val
|
||||
&& (OPB.integer_var < 0 || OPB.integer_var >=
|
||||
|
@ -525,7 +532,6 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to address an invalid "
|
||||
"field in an edict");
|
||||
return;
|
||||
}
|
||||
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
||||
OPC.integer_var = &ed->v[OPB.integer_var] - pr->pr_globals;
|
||||
|
@ -554,7 +560,6 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to read an out of "
|
||||
"bounds edict number");
|
||||
return;
|
||||
}
|
||||
if (pr_boundscheck->int_val
|
||||
&& (OPB.integer_var < 0 || OPB.integer_var >=
|
||||
|
@ -562,7 +567,6 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to read an invalid "
|
||||
"field in an edict");
|
||||
return;
|
||||
}
|
||||
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
||||
OPC.integer_var = ed->v[OPB.integer_var].integer_var;
|
||||
|
@ -574,7 +578,6 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to read an out of "
|
||||
"bounds edict number");
|
||||
return;
|
||||
}
|
||||
if (pr_boundscheck->int_val
|
||||
&& (OPB.integer_var < 0
|
||||
|
@ -582,7 +585,6 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to read an invalid "
|
||||
"field in an edict");
|
||||
return;
|
||||
}
|
||||
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
||||
memcpy (&OPC, &ed->v[OPB.integer_var], 3 * sizeof (OPC));
|
||||
|
@ -707,7 +709,6 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
&& (OPA.uinteger_var >= pr->progs->numstatements)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Invalid jump destination");
|
||||
return;
|
||||
}
|
||||
st = &pr->pr_statements[OPA.uinteger_var];
|
||||
break;
|
||||
|
@ -720,7 +721,6 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
&& (pointer >= pr->progs->numstatements)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Invalid jump destination");
|
||||
return;
|
||||
}
|
||||
st = &pr->pr_statements[pointer];
|
||||
break;
|
||||
|
@ -758,8 +758,10 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
case OP_RETURN:
|
||||
memcpy (&pr->pr_globals[OFS_RETURN], &OPA, 3 * sizeof (OPA));
|
||||
st = &pr->pr_statements[PR_LeaveFunction (pr)];
|
||||
if (pr->pr_depth == exitdepth)
|
||||
if (pr->pr_depth == exitdepth) {
|
||||
Sys_PopSignalHook ();
|
||||
return; // all done
|
||||
}
|
||||
break;
|
||||
case OP_STATE:
|
||||
ed = PROG_TO_EDICT (pr, *pr->globals.self);
|
||||
|
@ -868,7 +870,6 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs boundcheck failed at line number "
|
||||
"%d, value is < 0 or >= %d", st->b, st->c);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
113
libs/util/sys.c
113
libs/util/sys.c
|
@ -54,6 +54,8 @@ static const char rcsid[] =
|
|||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -133,7 +135,7 @@ const char sys_char_map[256] = {
|
|||
|
||||
#ifndef USE_INTEL_ASM
|
||||
void
|
||||
Sys_MaskExceptions (void)
|
||||
Sys_MaskFPUExceptions (void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
@ -573,3 +575,112 @@ Sys_ConsoleInput (void)
|
|||
return text;
|
||||
#endif
|
||||
}
|
||||
|
||||
static jmp_buf aiee_abort;
|
||||
|
||||
typedef struct sh_stack_s {
|
||||
struct sh_stack_s *next;
|
||||
void (*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 void *signal_hook_data;
|
||||
|
||||
void
|
||||
Sys_PushSignalHook (void (*hook)(int, void *), void *data)
|
||||
{
|
||||
sh_stack_t *s;
|
||||
|
||||
if (free_sh) {
|
||||
s = free_sh;
|
||||
} else {
|
||||
s = malloc (sizeof (sh_stack_t));
|
||||
s->next = 0;
|
||||
}
|
||||
s->signal_hook = signal_hook;
|
||||
s->data = signal_hook_data;
|
||||
signal_hook = hook;
|
||||
signal_hook_data = data;
|
||||
|
||||
free_sh = s->next;
|
||||
s->next = sh_stack;
|
||||
sh_stack = s;
|
||||
}
|
||||
|
||||
void
|
||||
Sys_PopSignalHook (void)
|
||||
{
|
||||
if (sh_stack) {
|
||||
sh_stack_t *s;
|
||||
|
||||
signal_hook = sh_stack->signal_hook;
|
||||
signal_hook_data = sh_stack->data;
|
||||
|
||||
s = sh_stack->next;
|
||||
sh_stack->next = free_sh;
|
||||
free_sh = sh_stack;
|
||||
sh_stack = s;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
aiee (int sig)
|
||||
{
|
||||
printf ("AIEE, signal %d in shutdown code, giving up\n", sig);
|
||||
longjmp (aiee_abort, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
signal_handler (int sig)
|
||||
{
|
||||
printf ("Received signal %d, exiting...\n", sig);
|
||||
|
||||
switch (sig) {
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
signal (SIGHUP, SIG_DFL);
|
||||
signal (SIGINT, SIG_DFL);
|
||||
signal (SIGTERM, SIG_DFL);
|
||||
Sys_Quit ();
|
||||
default:
|
||||
signal (SIGQUIT, aiee);
|
||||
signal (SIGILL, aiee);
|
||||
signal (SIGTRAP, aiee);
|
||||
signal (SIGIOT, aiee);
|
||||
signal (SIGBUS, aiee);
|
||||
signal (SIGSEGV, aiee);
|
||||
|
||||
if (!setjmp (aiee_abort)) {
|
||||
if (signal_hook)
|
||||
signal_hook (sig, signal_hook_data);
|
||||
Sys_Shutdown ();
|
||||
}
|
||||
|
||||
signal (SIGQUIT, SIG_DFL);
|
||||
signal (SIGILL, SIG_DFL);
|
||||
signal (SIGTRAP, SIG_DFL);
|
||||
signal (SIGIOT, SIG_DFL);
|
||||
signal (SIGBUS, SIG_DFL);
|
||||
signal (SIGSEGV, SIG_DFL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Sys_Init (void)
|
||||
{
|
||||
// catch signals
|
||||
signal (SIGHUP, signal_handler);
|
||||
signal (SIGINT, signal_handler);
|
||||
signal (SIGQUIT, signal_handler);
|
||||
signal (SIGILL, signal_handler);
|
||||
signal (SIGTRAP, signal_handler);
|
||||
signal (SIGIOT, signal_handler);
|
||||
signal (SIGBUS, signal_handler);
|
||||
signal (SIGSEGV, signal_handler);
|
||||
signal (SIGTERM, signal_handler);
|
||||
// signal (SIGFPE, signal_handler);
|
||||
}
|
||||
|
|
|
@ -74,12 +74,12 @@ C(name):
|
|||
|
||||
.text
|
||||
|
||||
F_BEGIN(Sys_MaskExceptions)
|
||||
F_BEGIN(Sys_MaskFPUExceptions)
|
||||
got_base(1)
|
||||
fnstenv got_var(fpenv)
|
||||
orl $0x3F,got_var(fpenv)
|
||||
fldenv got_var(fpenv)
|
||||
|
||||
ret
|
||||
F_END(Sys_MaskExceptions)
|
||||
F_END(Sys_MaskFPUExceptions)
|
||||
#endif /* USE_INTEL_ASM */
|
||||
|
|
|
@ -45,11 +45,6 @@ static const char rcsid[] =
|
|||
# include <execinfo.h>
|
||||
#endif
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ipc.h>
|
||||
|
@ -114,25 +109,6 @@ static int xss_interval;
|
|||
static int xss_blanking;
|
||||
static int xss_exposures;
|
||||
|
||||
|
||||
void
|
||||
dump_core_callback (cvar_t *sys_dump_core)
|
||||
{
|
||||
#ifndef HAVE_UNISTD_H
|
||||
if (sys_dump_core->int_val)
|
||||
Con_Printf ("support for dumping core has not been compiled in!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
backtrace_callback (cvar_t *sys_backtrace)
|
||||
{
|
||||
#ifndef HAVE_EXECINFO_H
|
||||
if (sys_backtrace->int_val)
|
||||
Con_Printf ("support for printing backtraces has not been compiled in!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
qboolean
|
||||
X11_AddEvent (int event, void (*event_handler) (XEvent *))
|
||||
{
|
||||
|
@ -191,52 +167,6 @@ X11_ProcessEvents (void)
|
|||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// Tragic death handler
|
||||
// ========================================================================
|
||||
|
||||
static jmp_buf aiee_abort;
|
||||
|
||||
static void
|
||||
aiee (int sig)
|
||||
{
|
||||
printf ("AIEE, signal %d in shutdown code, giving up\n", sig);
|
||||
longjmp (aiee_abort, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
TragicDeath (int sig)
|
||||
{
|
||||
printf ("Received signal %d, exiting...\n", sig);
|
||||
|
||||
switch (sig) {
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
signal (SIGHUP, SIG_DFL);
|
||||
signal (SIGINT, SIG_DFL);
|
||||
signal (SIGTERM, SIG_DFL);
|
||||
Sys_Quit ();
|
||||
default:
|
||||
signal (SIGQUIT, aiee);
|
||||
signal (SIGILL, aiee);
|
||||
signal (SIGTRAP, aiee);
|
||||
signal (SIGIOT, aiee);
|
||||
signal (SIGBUS, aiee);
|
||||
signal (SIGSEGV, aiee);
|
||||
|
||||
if (!setjmp (aiee_abort))
|
||||
Sys_Shutdown ();
|
||||
|
||||
signal (SIGQUIT, SIG_DFL);
|
||||
signal (SIGILL, SIG_DFL);
|
||||
signal (SIGTRAP, SIG_DFL);
|
||||
signal (SIGIOT, SIG_DFL);
|
||||
signal (SIGBUS, SIG_DFL);
|
||||
signal (SIGSEGV, SIG_DFL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
X11_OpenDisplay (void)
|
||||
{
|
||||
|
@ -250,18 +180,6 @@ X11_OpenDisplay (void)
|
|||
x_screen = DefaultScreen (x_disp);
|
||||
x_root = RootWindow (x_disp, x_screen);
|
||||
|
||||
// catch signals
|
||||
signal (SIGHUP, TragicDeath);
|
||||
signal (SIGINT, TragicDeath);
|
||||
signal (SIGQUIT, TragicDeath);
|
||||
signal (SIGILL, TragicDeath);
|
||||
signal (SIGTRAP, TragicDeath);
|
||||
signal (SIGIOT, TragicDeath);
|
||||
signal (SIGBUS, TragicDeath);
|
||||
signal (SIGSEGV, TragicDeath);
|
||||
signal (SIGTERM, TragicDeath);
|
||||
// signal (SIGFPE, TragicDeath);
|
||||
|
||||
// for debugging only
|
||||
XSynchronize (x_disp, True);
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ static const char rcsid[] =
|
|||
#endif
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <sys/signal.h>
|
||||
|
||||
#include "QF/console.h"
|
||||
#include "QF/cvar.h"
|
||||
|
@ -166,63 +165,6 @@ VID_Shutdown (void)
|
|||
qf_fxMesaDestroyContext (fc);
|
||||
}
|
||||
|
||||
static jmp_buf aiee_abort;
|
||||
|
||||
static void
|
||||
aiee (int sig)
|
||||
{
|
||||
printf ("AIEE, signal %d in shutdown code, giving up\n", sig);
|
||||
longjmp (aiee_abort, 1);
|
||||
}
|
||||
|
||||
void
|
||||
signal_handler (int sig)
|
||||
{
|
||||
printf ("Received signal %d, exiting...\n", sig);
|
||||
|
||||
switch (sig) {
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
signal (SIGHUP, SIG_DFL);
|
||||
signal (SIGINT, SIG_DFL);
|
||||
signal (SIGTERM, SIG_DFL);
|
||||
Sys_Quit ();
|
||||
default:
|
||||
signal (SIGQUIT, aiee);
|
||||
signal (SIGILL, aiee);
|
||||
signal (SIGTRAP, aiee);
|
||||
signal (SIGIOT, aiee);
|
||||
signal (SIGBUS, aiee);
|
||||
signal (SIGSEGV, aiee);
|
||||
|
||||
if (!setjmp (aiee_abort))
|
||||
Sys_Shutdown ();
|
||||
|
||||
signal (SIGQUIT, SIG_DFL);
|
||||
signal (SIGILL, SIG_DFL);
|
||||
signal (SIGTRAP, SIG_DFL);
|
||||
signal (SIGIOT, SIG_DFL);
|
||||
signal (SIGBUS, SIG_DFL);
|
||||
signal (SIGSEGV, SIG_DFL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
InitSig (void)
|
||||
{
|
||||
signal (SIGHUP, signal_handler);
|
||||
signal (SIGINT, signal_handler);
|
||||
signal (SIGQUIT, signal_handler);
|
||||
signal (SIGILL, signal_handler);
|
||||
signal (SIGTRAP, signal_handler);
|
||||
// signal(SIGIOT, signal_handler);
|
||||
signal (SIGBUS, signal_handler);
|
||||
// signal(SIGFPE, signal_handler);
|
||||
signal (SIGSEGV, signal_handler);
|
||||
signal (SIGTERM, signal_handler);
|
||||
}
|
||||
|
||||
void
|
||||
GL_Init (void)
|
||||
{
|
||||
|
@ -396,8 +338,6 @@ VID_Init (unsigned char *palette)
|
|||
vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0);
|
||||
vid.numpages = 2;
|
||||
|
||||
InitSig (); // trap evil signals
|
||||
|
||||
vid_gamma_avail = 1;
|
||||
|
||||
GL_Init ();
|
||||
|
|
|
@ -859,6 +859,8 @@ Host_Init (void)
|
|||
Cvar_Init ();
|
||||
Sys_Init_Cvars ();
|
||||
|
||||
Sys_Init ();
|
||||
|
||||
Cmd_Init ();
|
||||
|
||||
// execute +set as early as possible
|
||||
|
|
|
@ -80,7 +80,7 @@ startup (void)
|
|||
{
|
||||
#ifdef WIN32
|
||||
OSVERSIONINFO vinfo;
|
||||
Sys_MaskExceptions ();
|
||||
Sys_MaskFPUExceptions ();
|
||||
|
||||
// make sure the timer is high precision, otherwise NT gets 18ms resolution
|
||||
timeBeginPeriod (1);
|
||||
|
|
|
@ -96,7 +96,7 @@ startup (void)
|
|||
unsigned int lowpart, highpart;
|
||||
OSVERSIONINFO vinfo;
|
||||
|
||||
Sys_MaskExceptions ();
|
||||
Sys_MaskFPUExceptions ();
|
||||
|
||||
if (!QueryPerformanceFrequency (&PerformanceFreq))
|
||||
Sys_Error ("No hardware timer available");
|
||||
|
|
|
@ -1667,6 +1667,8 @@ Host_Init (void)
|
|||
Cvar_Init ();
|
||||
Sys_Init_Cvars ();
|
||||
|
||||
Sys_Init ();
|
||||
|
||||
Cmd_Init ();
|
||||
|
||||
// execute +set as early as possible
|
||||
|
|
|
@ -2406,6 +2406,8 @@ SV_Init (void)
|
|||
Cvar_Init ();
|
||||
Sys_Init_Cvars ();
|
||||
|
||||
Sys_Init ();
|
||||
|
||||
Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL);
|
||||
|
||||
Cmd_Init ();
|
||||
|
|
|
@ -36,7 +36,6 @@ static const char rcsid[] =
|
|||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
|
||||
#include "QF/cmd.h"
|
||||
#include "QF/csqc.h" //FIXME d'oh, dumb name after all
|
||||
|
@ -67,7 +66,6 @@ func_t SpectatorThink;
|
|||
func_t UserInfoCallback;
|
||||
|
||||
static int reserved_edicts = MAX_CLIENTS;
|
||||
static void (*old_seg_handler) (int);
|
||||
|
||||
static void
|
||||
free_edict (progs_t *pr, edict_t *ent)
|
||||
|
@ -165,14 +163,6 @@ parse_field (progs_t *pr, const char *key, const char *value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
seg_fault_handler(int whatever)
|
||||
{
|
||||
if (sv_pr_state.pr_xfunction)
|
||||
PR_DumpState (&sv_pr_state);
|
||||
signal (SIGSEGV, old_seg_handler);
|
||||
}
|
||||
|
||||
void
|
||||
SV_LoadProgs (void)
|
||||
{
|
||||
|
@ -379,8 +369,6 @@ SV_Progs_Init (void)
|
|||
"Display summary information on the edicts in the game.");
|
||||
Cmd_AddCommand ("profile", PR_Profile_f, "FIXME: Report information about "
|
||||
"QuakeC Stuff (\?\?\?) No Description");
|
||||
|
||||
old_seg_handler = signal (SIGSEGV, seg_fault_handler);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue