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:
Bill Currie 2002-08-20 23:04:57 +00:00
parent 118e982edd
commit 5009213564
12 changed files with 137 additions and 171 deletions

View file

@ -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

View file

@ -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;

View file

@ -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);
}

View file

@ -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 */

View file

@ -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);

View file

@ -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 ();

View file

@ -859,6 +859,8 @@ Host_Init (void)
Cvar_Init ();
Sys_Init_Cvars ();
Sys_Init ();
Cmd_Init ();
// execute +set as early as possible

View file

@ -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);

View file

@ -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");

View file

@ -1667,6 +1667,8 @@ Host_Init (void)
Cvar_Init ();
Sys_Init_Cvars ();
Sys_Init ();
Cmd_Init ();
// execute +set as early as possible

View file

@ -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 ();

View file

@ -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