From 546e333a3cd71049dfc8e05570f8dd08fa61830c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 3 Jan 2016 23:04:00 +0900 Subject: [PATCH] Allow Sys_Error to be hooked. This makes debugging builtins that wrap normal functions a little easier by giving a progs dump when such an error occurs. --- include/QF/sys.h | 5 +++++ libs/gamecode/pr_exec.c | 19 +++++++++++++++---- libs/util/sys.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index 1fe994c94..8bbb08781 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -63,13 +63,18 @@ int Sys_isdir (const char *path); int Sys_mkdir (const char *path); typedef void (*sys_printf_t) (const char *fmt, va_list args); +typedef void (*sys_error_t) (void *data); void Sys_SetStdPrintf (sys_printf_t func); void Sys_SetErrPrintf (sys_printf_t func); +void Sys_PushErrorHandler (sys_error_t func, void *data); +void Sys_PopErrorHandler (void); + void Sys_Print (FILE *stream, const char *fmt, va_list args); void Sys_Printf (const char *fmt, ...) __attribute__((format(printf,1,2))); void Sys_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); +void Sys_FatalError (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); void Sys_Quit (void) __attribute__((noreturn)); void Sys_Shutdown (void); void Sys_RegisterShutdown (void (*func) (void)); diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 0ebf7dbef..579992271 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -328,6 +328,14 @@ signal_hook (int sig, void *data) return 0; } +static void +error_handler (void *data) +{ + progs_t *pr = (progs_t *) data; + PR_DumpState (pr); + fflush (stdout); +} + VISIBLE int PR_CallFunction (progs_t *pr, func_t fnum) { @@ -370,11 +378,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) startprofile = profile = 0; Sys_PushSignalHook (signal_hook, pr); + Sys_PushErrorHandler (error_handler, pr); if (!PR_CallFunction (pr, fnum)) { // called a builtin instead of progs code - Sys_PopSignalHook (); - return; + goto exit_program; } st = pr->pr_statements + pr->pr_xstatement; @@ -964,8 +972,8 @@ op_call: if (pr->pr_depth == exitdepth) { if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth) pr->pr_trace = false; - Sys_PopSignalHook (); - return; // all done + // all done + goto exit_program; } break; case OP_STATE: @@ -1116,4 +1124,7 @@ op_call: PR_RunError (pr, "watchpoint hit: %d -> %d", old_val.integer_var, watch->integer_var); } +exit_program: + Sys_PopErrorHandler (); + Sys_PopSignalHook (); } diff --git a/libs/util/sys.c b/libs/util/sys.c index 4e2e111e2..1b6a9c269 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -79,6 +79,7 @@ #include "qfalloca.h" +#include "QF/alloc.h" #include "QF/cmd.h" #include "QF/cvar.h" #include "QF/dstring.h" @@ -107,8 +108,17 @@ typedef struct shutdown_list_s { void (*func)(void); } shutdown_list_t; +typedef struct error_handler_s { + struct error_handler_s *next; + sys_error_t func; + void *data; +} error_handler_t; + static shutdown_list_t *shutdown_list; +static error_handler_t *error_handler_freelist; +static error_handler_t *error_handler; + #ifndef _WIN32 static int do_stdin = 1; qboolean stdin_ready; @@ -493,6 +503,31 @@ Sys_Quit (void) exit (0); } +VISIBLE void +Sys_PushErrorHandler (sys_error_t func, void *data) +{ + error_handler_t *eh; + ALLOC (16, error_handler_t, error_handler, eh); + eh->func = func; + eh->data = data; + eh->next = error_handler; + error_handler = eh; +} + +VISIBLE void +Sys_PopErrorHandler (void) +{ + error_handler_t *eh; + + if (!error_handler) { + Sys_Error ("Sys_PopErrorHandler: no handler to pop"); + } + eh = error_handler; + error_handler = eh->next; + FREE (error_handler, eh); +} + + VISIBLE void Sys_Error (const char *error, ...) { @@ -515,6 +550,10 @@ Sys_Error (const char *error, ...) sys_err_printf_function (error, args); va_end (args); + if (error_handler) { + error_handler->func (error_handler->data); + } + Sys_Shutdown (); if (sys_err_printf_function != Sys_ErrPrintf) {