]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
SVVM: fully shut down when stopping a server to avoid segfaulting later
authorbones_was_here <bones_was_here@xonotic.au>
Tue, 6 Feb 2024 11:22:06 +0000 (21:22 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Tue, 6 Feb 2024 11:30:23 +0000 (21:30 +1000)
Fixes segfaults when functions that check if the progs is loaded (to
avoid crashing) are called after stopping a server.
Example repro: load a map, disconnect, `set sv_cheats 0`.

Fixes wrong SV_Shutdown order: SV_DropClient must be done before
shutting down SVQC because it calls SVQC functions.

Deduplicates SVQC shutdown.

Signed-off-by: bones_was_here <bones_was_here@xonotic.au>
sv_main.c

index 65ba374dc84ffe15bd195b1d5ae8026351dd8679..fed375eb8bfd2e4da21d116c6757d0c1a1970613 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -1816,16 +1816,7 @@ void SV_SpawnServer (const char *map)
        }
 
        if(sv.active)
-       {
-               World_End(&sv.world);
-               if(PRVM_serverfunction(SV_Shutdown))
-               {
-                       func_t s = PRVM_serverfunction(SV_Shutdown);
-                       PRVM_serverglobalfloat(time) = sv.time;
-                       PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
-                       prog->ExecuteProgram(prog, s,"SV_Shutdown() required");
-               }
-       }
+               PRVM_Prog_Reset(prog); // calls graceful SVQC shutdown in SVVM_reset_cmd
 
        // free q3 shaders so that any newly downloaded shaders will be active
        Mod_FreeQ3Shaders();
@@ -2125,22 +2116,13 @@ void SV_Shutdown(void)
        NetConn_Heartbeat(2);
        NetConn_Heartbeat(2);
 
-// make sure all the clients know we're disconnecting
-       World_End(&sv.world);
-       if(prog->loaded)
-       {
-               if(PRVM_serverfunction(SV_Shutdown))
-               {
-                       func_t s = PRVM_serverfunction(SV_Shutdown);
-                       PRVM_serverglobalfloat(time) = sv.time;
-                       PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
-                       prog->ExecuteProgram(prog, s,"SV_Shutdown() required");
-               }
-       }
+       // make sure all the clients know we're disconnecting
        for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
                if (host_client->active)
                        SV_DropClient(false, "Server shutting down"); // server shutdown
 
+       PRVM_Prog_Reset(prog); // calls graceful SVQC shutdown in SVVM_reset_cmd
+
        NetConn_CloseServerPorts();
 
        sv.active = false;