From 50092135640752533c45942df13f1b32d136c596 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Aug 2002 23:04:57 +0000 Subject: [PATCH] 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:) --- include/QF/sys.h | 4 +- libs/gamecode/engine/pr_exec.c | 23 +++--- libs/util/sys.c | 113 +++++++++++++++++++++++++++++- libs/util/sys_ia32.S | 4 +- libs/video/targets/context_x11.c | 82 ---------------------- libs/video/targets/vid_3dfxsvga.c | 60 ---------------- nq/source/host.c | 2 + nq/source/sys_sdl.c | 2 +- nq/source/sys_win.c | 2 +- qw/source/cl_main.c | 2 + qw/source/sv_main.c | 2 + qw/source/sv_progs.c | 12 ---- 12 files changed, 137 insertions(+), 171 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index 74d7735ad..b276cb246 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -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 diff --git a/libs/gamecode/engine/pr_exec.c b/libs/gamecode/engine/pr_exec.c index 28db49dfd..904dc1b0d 100644 --- a/libs/gamecode/engine/pr_exec.c +++ b/libs/gamecode/engine/pr_exec.c @@ -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; diff --git a/libs/util/sys.c b/libs/util/sys.c index 68551d3b0..5e7486850 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -54,6 +54,8 @@ static const char rcsid[] = # include #endif +#include +#include #include #include #include @@ -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); +} diff --git a/libs/util/sys_ia32.S b/libs/util/sys_ia32.S index 3096c79dd..93133872a 100644 --- a/libs/util/sys_ia32.S +++ b/libs/util/sys_ia32.S @@ -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 */ diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index e3d558e23..31c82e292 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -45,11 +45,6 @@ static const char rcsid[] = # include #endif -#include -#include -#include -#include -#include #include #include #include @@ -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); diff --git a/libs/video/targets/vid_3dfxsvga.c b/libs/video/targets/vid_3dfxsvga.c index c5d3e9175..d2a9bcbf8 100644 --- a/libs/video/targets/vid_3dfxsvga.c +++ b/libs/video/targets/vid_3dfxsvga.c @@ -43,7 +43,6 @@ static const char rcsid[] = #endif #include -#include #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 (); diff --git a/nq/source/host.c b/nq/source/host.c index 0fa039c57..b6ce36225 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -859,6 +859,8 @@ Host_Init (void) Cvar_Init (); Sys_Init_Cvars (); + Sys_Init (); + Cmd_Init (); // execute +set as early as possible diff --git a/nq/source/sys_sdl.c b/nq/source/sys_sdl.c index 138ea81f8..c6b62db02 100644 --- a/nq/source/sys_sdl.c +++ b/nq/source/sys_sdl.c @@ -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); diff --git a/nq/source/sys_win.c b/nq/source/sys_win.c index 61396fb6e..0d9c8859f 100644 --- a/nq/source/sys_win.c +++ b/nq/source/sys_win.c @@ -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"); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 8c1592309..d2772a9a0 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1667,6 +1667,8 @@ Host_Init (void) Cvar_Init (); Sys_Init_Cvars (); + Sys_Init (); + Cmd_Init (); // execute +set as early as possible diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index d451f01cf..9188bda1f 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -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 (); diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 4a6ee9036..e56e8c836 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -36,7 +36,6 @@ static const char rcsid[] = #ifdef HAVE_STRINGS_H # include #endif -#include #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