]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
PRVM: refactor error handling
authorbones_was_here <bones_was_here@xonotic.au>
Sun, 11 Feb 2024 13:54:39 +0000 (23:54 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Mon, 26 Feb 2024 16:06:05 +0000 (02:06 +1000)
Cleans up PRVM_Crash() calling and removes redundant code.
Directs menu errors to stderr instead of stdout.
Aborts if a loop is detected in MVM_error_cmd(), matching Host_Error().
Prevents QC's CSQC_Shutdown() being called when CSQC crashes.
Makes cvar prvm_errordump ignore MENUQC crashes.
Improves some messages and comments.

Signed-off-by: bones_was_here <bones_was_here@xonotic.au>
host.c
menu.c
progsvm.h
prvm_exec.c

diff --git a/host.c b/host.c
index de40ce7f4ace2882fbd5df95e89b3b2283e8b29f..d8d98795f6ac0a89fa80616e48569302e50c248a 100644 (file)
--- a/host.c
+++ b/host.c
@@ -116,33 +116,22 @@ void Host_Error (const char *error, ...)
        dp_strlcpy(hosterrorstring2, hosterrorstring1, sizeof(hosterrorstring2));
 
        CL_Parse_DumpPacket();
-
        CL_Parse_ErrorCleanUp();
 
-       //PR_Crash();
-
        // print out where the crash happened, if it was caused by QC (and do a cleanup)
-       PRVM_Crash(SVVM_prog);
-       PRVM_Crash(CLVM_prog);
-#ifdef CONFIG_MENU
-       PRVM_Crash(MVM_prog);
-#endif
-
-       Cvar_SetValueQuick(&csqc_progcrc, -1);
-       Cvar_SetValueQuick(&csqc_progsize, -1);
+       PRVM_Crash();
 
        if(host.hook.SV_Shutdown)
                host.hook.SV_Shutdown();
 
        if (cls.state == ca_dedicated)
-               Sys_Abort ("Host_Error: %s",hosterrorstring2);        // dedicated servers exit
+               Sys_Abort("Host_Error: %s", hosterrorstring1);        // dedicated servers exit
 
        // prevent an endless loop if the error was triggered by a command
        Cbuf_Clear(cmd_local->cbuf);
 
-       // DP8 TODO: send a disconnect message indicating we errored out, see Sys_Abort() and Sys_HandleCrash()
-       CL_Disconnect();
-       cls.demonum = -1;
+       CL_DisconnectEx(false, "Host_Error: %s", hosterrorstring1);
+       cls.demonum = -1; // stop demo loop
 
        hosterror = false;
 
diff --git a/menu.c b/menu.c
index 92e95ed1f0b60811f5312f00636790de5bc3cb59..996f1711d66a0bb0287f7760684fef04a19a31bd 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -5211,36 +5211,34 @@ void MR_SetRouting (qbool forceold);
 void MVM_error_cmd(const char *format, ...) DP_FUNC_PRINTF(1);
 void MVM_error_cmd(const char *format, ...)
 {
-       prvm_prog_t *prog = MVM_prog;
        static qbool processingError = false;
        char errorstring[MAX_INPUTLINE];
        va_list argptr;
+       int outfd = sys.outfd;
+
+       // set output to stderr
+       sys.outfd = fileno(stderr);
 
        va_start (argptr, format);
        dpvsnprintf (errorstring, sizeof(errorstring), format, argptr);
        va_end (argptr);
 
        if (host.framecount < 3)
-               Sys_Abort("Menu_Error: %s\n", errorstring);
+               Sys_Abort("Menu_Error: %s", errorstring);
 
-       Con_Printf( "Menu_Error: %s\n", errorstring );
+       Con_Printf(CON_ERROR "Menu_Error: %s\n", errorstring);
 
-       if( !processingError ) {
+       if(!processingError)
+       {
                processingError = true;
-               PRVM_Crash(prog);
+               PRVM_Crash();
                processingError = false;
-       } else {
-               Con_Printf( "Menu_Error: Recursive call to MVM_error_cmd (from PRVM_Crash)!\n" );
        }
+       else
+               Sys_Abort("Menu_Error: Recursive call to MVM_error_cmd (from PRVM_Crash)!");
 
-       // fall back to the normal menu
-
-       // say it
-       Con_Print("Falling back to normal menu\n");
-
+       Con_Print("Falling back to engine menu\n");
        key_dest = key_game;
-
-       // init the normal menu now -> this will also correct the menu router pointers
        MR_SetRouting (true);
 
        // reset the active scene, too (to be on the safe side ;))
@@ -5249,6 +5247,9 @@ void MVM_error_cmd(const char *format, ...)
        // prevent an endless loop if the error was triggered by a command
        Cbuf_Clear(cmd_local->cbuf);
 
+       // restore configured outfd
+       sys.outfd = outfd;
+
        // Let video start at least
        Host_AbortCurrentFrame();
 }
index 4c6a7f4d34ea4b407bf1f8e1203d7f9dbf893338..1f8e478ffe65b28b5bd3f927ead8b2664b6b86ea 100644 (file)
--- a/progsvm.h
+++ b/progsvm.h
@@ -822,7 +822,7 @@ void PRVM_CallProfile_f(struct cmd_state_s *cmd);
 void PRVM_PrintFunction_f(struct cmd_state_s *cmd);
 
 void PRVM_PrintState(prvm_prog_t *prog, int stack_index);
-void PRVM_Crash(prvm_prog_t *prog);
+void PRVM_Crash(void);
 void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize);
 const char *PRVM_AllocationOrigin(prvm_prog_t *prog);
 void PRVM_GarbageCollection(prvm_prog_t *prog);
index f24838e5db588dd11e2b645f1dbde2b6188ac73a..d29aa7f559f7c68d44c382d53ce8eedbab0672c4 100644 (file)
@@ -715,28 +715,30 @@ void PRVM_PrintState(prvm_prog_t *prog, int stack_index)
 }
 
 extern cvar_t prvm_errordump;
-void PRVM_Crash(prvm_prog_t *prog)
+void PRVM_Crash(void)
 {
+       prvm_prog_t *prog;
        char vabuf[1024];
-       int outfd = sys.outfd;
-
-       if (prog == NULL)
-               return;
-       if (!prog->loaded)
-               return;
+       int i;
 
-       // set output to stderr
-       sys.outfd = fileno(stderr);
+       // determine which program crashed
+       for (i = 0; i < PRVM_PROG_MAX; ++i)
+               if (PRVM_GetProg(i)->loaded && PRVM_GetProg(i)->depth > 0)
+                       break;
+       if (i >= PRVM_PROG_MAX)
+               return; // none of them crashed
+       prog = PRVM_GetProg(i);
 
-       PRVM_serverfunction(SV_Shutdown) = 0; // don't call SV_Shutdown on crash
+       Con_Printf("QuakeC crash report for %s:\n", prog->name);
+       PRVM_PrintState(prog, 0);
 
-       if( prog->depth > 0 )
-       {
-               Con_Printf("QuakeC crash report for %s:\n", prog->name);
-               PRVM_PrintState(prog, 0);
-       }
+       // don't call graceful shutdown on crash
+       if (prog == SVVM_prog)
+               PRVM_serverfunction(SV_Shutdown) = 0;
+       else if (prog == CLVM_prog)
+               PRVM_clientfunction(CSQC_Shutdown) = 0;
 
-       if(prvm_errordump.integer)
+       if(prvm_errordump.integer && (prog == SVVM_prog || prog == CLVM_prog))
        {
                // make a savegame
                SV_Savegame_to(prog, va(vabuf, sizeof(vabuf), "crash-%s.dmp", prog->name));
@@ -745,15 +747,6 @@ void PRVM_Crash(prvm_prog_t *prog)
        // dump the stack so host_error can shutdown functions
        prog->depth = 0;
        prog->localstack_used = 0;
-
-       // delete all tempstrings (FIXME: is this safe in VM->engine->VM recursion?)
-       prog->tempstringsbuf.cursize = 0;
-
-       // reset the prog pointer
-       prog = NULL;
-
-       // restore configured outfd
-       sys.outfd = outfd;
 }
 
 /*
@@ -1031,7 +1024,7 @@ cleanup:
        if (prog == SVVM_prog)
                SV_FlushBroadcastMessages();
 }
-#endif
+#endif // CONFIG_MENU
 
 /*
 ====================
@@ -1140,7 +1133,7 @@ cleanup:
        if (prog == SVVM_prog)
                SV_FlushBroadcastMessages();
 }
-#endif
+#endif // PROFILING
 
 /*
 ====================