]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
sys: prevent loops in signal handlers
authorbones_was_here <bones_was_here@xonotic.au>
Mon, 26 Feb 2024 18:53:26 +0000 (04:53 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Mon, 26 Feb 2024 18:53:26 +0000 (04:53 +1000)
Fixes https://gitlab.com/xonotic/xonotic/-/issues/377

Signed-off-by: bones_was_here <bones_was_here@xonotic.au>
host.h
sys_shared.c

diff --git a/host.h b/host.h
index 89ea1f11947ac0dd5038d5e432d19971d7b4b099..986b3224fb460f9cc37cb1f34bcbc7fe83fbf707 100644 (file)
--- 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;
 
index 7ce69c3132be521c6173760e6df715c5bc2c6d4e..fa733ebf843790abc82ca03f78ca479232a0c718 100644 (file)
@@ -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);
        }