]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sys_shared.c
PRVM: fix null ptr deref in VM_getkeybind()
[xonotic/darkplaces.git] / sys_shared.c
index 6b5eef4343cce9360a15676626ca2671932fe173..745a839eb6ae0f1bfe9594a6f4695e5e9354d308 100644 (file)
 #include "thread.h"
 #include "libcurl.h"
 
-#ifdef WIN32
-       // Microsoft's compiler complains about portable code
-       #pragma warning(disable : 4996)
-#endif
 
 sys_t sys;
 
@@ -60,33 +56,6 @@ char *Sys_TimeString(const char *timeformat)
 }
 
 
-void Sys_Quit (int returnvalue)
-{
-       // Unlock mutexes because the quit command may jump directly here, causing a deadlock
-       if ((cmd_local)->cbuf->lock)
-               Cbuf_Unlock((cmd_local)->cbuf);
-       SV_UnlockThreadMutex();
-       TaskQueue_Frame(true);
-
-       if (Sys_CheckParm("-profilegameonly"))
-               Sys_AllowProfiling(false);
-       host.state = host_shutdown;
-       Host_Shutdown();
-
-#ifdef __ANDROID__
-       Sys_AllowProfiling(false);
-#endif
-
-#ifndef WIN32
-       fcntl(fileno(stdout), F_SETFL, fcntl(fileno(stdout), F_GETFL, 0) & ~O_NONBLOCK);
-       fcntl(fileno(stderr), F_SETFL, fcntl(fileno(stderr), F_GETFL, 0) & ~O_NONBLOCK);
-#endif
-       fflush(stdout);
-       fflush(stderr);
-
-       exit(returnvalue);
-}
-
 #ifdef __cplusplus
 extern "C"
 #endif
@@ -413,7 +382,7 @@ double Sys_DirtyTime(void)
                double old_benchmark_time = benchmark_time;
                benchmark_time += 1;
                if(benchmark_time == old_benchmark_time)
-                       Sys_Abort("sys_usenoclockbutbenchmark cannot run any longer, sorry");
+                       Sys_Error("sys_usenoclockbutbenchmark cannot run any longer, sorry");
                return benchmark_time * 0.000001;
        }
 #if HAVE_QUERYPERFORMANCECOUNTER
@@ -494,7 +463,7 @@ double Sys_DirtyTime(void)
        }
 #else
        // fallback for using the SDL timer if no other timer is available
-       // this calls Sys_Abort() if not linking against SDL
+       // this calls Sys_Error() if not linking against SDL
        return (double) Sys_SDL_GetTicks() / 1000.0;
 #endif
 }
@@ -523,7 +492,7 @@ double Sys_Sleep(double time)
                double old_benchmark_time = benchmark_time;
                benchmark_time += microseconds;
                if(benchmark_time == old_benchmark_time)
-                       Sys_Abort("sys_usenoclockbutbenchmark cannot run any longer, sorry");
+                       Sys_Error("sys_usenoclockbutbenchmark cannot run any longer, sorry");
                return 0;
        }
 
@@ -705,12 +674,15 @@ Startup and Shutdown
 ===============================================================================
 */
 
-void Sys_Abort (const char *error, ...)
+void Sys_Error (const char *error, ...)
 {
        va_list argptr;
        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
@@ -721,7 +693,7 @@ void Sys_Abort (const char *error, ...)
        dpvsnprintf (string, sizeof (string), error, argptr);
        va_end (argptr);
 
-       Con_Printf(CON_ERROR "Engine Abort: %s\n^9%s\n", string, engineversion);
+       Con_Printf(CON_ERROR "Engine Aborted: %s\n^9%s\n", string, engineversion);
 
        dp_strlcat(string, "\n\n", sizeof(string));
        dp_strlcat(string, engineversion, sizeof(string));
@@ -737,17 +709,16 @@ void Sys_Abort (const char *error, ...)
                sv.active = false; // make SV_DropClient() skip the QC stuff to avoid recursive errors
                for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
                        if (host_client->active)
-                               SV_DropClient(false, "Server abort!"); // closes demo file
+                               SV_DropClient(false, "Server aborted!"); // closes demo file
        }
        // don't want a dead window left blocking the OS UI or the abort dialog
        VID_Shutdown();
        S_StopAllSounds();
 
-       host.state = host_failed; // make Sys_HandleSignal() call exit()
-       Sys_SDL_Dialog("Engine Abort", string);
+       host.state = host_failed; // make Sys_HandleSignal() call _Exit()
+       Sys_SDL_Dialog("Engine Aborted", string);
 
        fflush(stderr);
-
        exit (1);
 }
 
@@ -983,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,7 +985,7 @@ static void Sys_HandleCrash(int sig)
        Sys_Print("\n", 1);
 #endif
 
-       // DP8 TODO: send a disconnect message indicating we crashed, see Sys_Abort() and Host_Error()
+       // DP8 TODO: send a disconnect message indicating we crashed, see Sys_Error() and Host_Error()
 
        // don't want a dead window left blocking the OS UI or the crash dialog
        VID_Shutdown();
@@ -1033,18 +1011,28 @@ static void Sys_HandleCrash(int sig)
        Sys_SDL_Dialog("Engine Crash", dialogtext);
 
        fflush(stderr); // not async-signal-safe :(
-       _Exit(sig);
+
+       // Continue execution with default signal handling.
+       // A real crash will be re-triggered so the platform can handle it,
+       // a fake crash (kill -SEGV) will cause a graceful shutdown.
+       signal(sig, SIG_DFL);
 }
 
 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);
        }
@@ -1103,7 +1091,16 @@ int main (int argc, char **argv)
 
        Host_Main();
 
-       Sys_Quit(0);
+#ifdef __ANDROID__
+       Sys_AllowProfiling(false);
+#endif
+
+#ifndef WIN32
+       fcntl(fileno(stdout), F_SETFL, fcntl(fileno(stdout), F_GETFL, 0) & ~O_NONBLOCK);
+       fcntl(fileno(stderr), F_SETFL, fcntl(fileno(stderr), F_GETFL, 0) & ~O_NONBLOCK);
+#endif
+       fflush(stdout);
+       fflush(stderr);
 
        return 0;
 }