From: bones_was_here Date: Mon, 26 Feb 2024 18:53:26 +0000 (+1000) Subject: sys: prevent loops in signal handlers X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=95ed24831ca8dcbf6ae8f886733c35ce2ad83272;p=xonotic%2Fdarkplaces.git sys: prevent loops in signal handlers Fixes https://gitlab.com/xonotic/xonotic/-/issues/377 Signed-off-by: bones_was_here --- diff --git a/host.h b/host.h index 89ea1f11..986b3224 100644 --- a/host.h +++ b/host.h @@ -24,6 +24,7 @@ typedef enum host_state_e host_init, host_loading, host_active, + host_failing, ///< crashing host_failed ///< crashed or aborted, SDL dialog open } host_state_t; diff --git a/sys_shared.c b/sys_shared.c index 7ce69c31..fa733ebf 100644 --- a/sys_shared.c +++ b/sys_shared.c @@ -680,6 +680,9 @@ void Sys_Abort (const char *error, ...) char string[MAX_INPUTLINE]; int i; + // Disable Sys_HandleSignal() but not Sys_HandleCrash() + host.state = host_shutdown; + // set output to blocking stderr sys.outfd = fileno(stderr); #ifndef WIN32 @@ -712,11 +715,10 @@ void Sys_Abort (const char *error, ...) VID_Shutdown(); S_StopAllSounds(); - host.state = host_failed; // make Sys_HandleSignal() call exit() + host.state = host_failed; // make Sys_HandleSignal() call _Exit() Sys_SDL_Dialog("Engine Abort", string); fflush(stderr); - exit (1); } @@ -952,7 +954,14 @@ static void Sys_HandleCrash(int sig) char **btstrings; #endif char dialogtext[3072]; - const char *sigdesc = Sys_SigDesc(sig); + const char *sigdesc; + + // Break any loop and disable Sys_HandleSignal() + if (host.state == host_failing || host.state == host_failed) + return; + host.state = host_failing; + + sigdesc = Sys_SigDesc(sig); // set output to blocking stderr and print header, backtrace, version sys.outfd = fileno(stderr); // not async-signal-safe :( @@ -1007,13 +1016,19 @@ static void Sys_HandleCrash(int sig) static void Sys_HandleSignal(int sig) { - const char *sigdesc = Sys_SigDesc(sig); + const char *sigdesc; + + // Break any loop, eg if each Sys_Print triggers a SIGPIPE + if (host.state == host_shutdown || host.state == host_failing) + return; + + sigdesc = Sys_SigDesc(sig); Sys_Print("\nReceived ", 10); Sys_Print(sigdesc, strlen(sigdesc)); Sys_Print(" signal, exiting...\n", 20); if (host.state == host_failed) { - // user is trying to kill the process while the dialog is open + // user is trying to kill the process while the SDL dialog is open fflush(stderr); // not async-signal-safe :( _Exit(sig); }