From: bones_was_here Date: Sun, 11 Feb 2024 13:54:39 +0000 (+1000) Subject: PRVM: refactor error handling X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=4d00f11db53273b8624b8ce95f066450dad0a298;p=xonotic%2Fdarkplaces.git PRVM: refactor error handling 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 --- diff --git a/host.c b/host.c index de40ce7f..d8d98795 100644 --- 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 92e95ed1..996f1711 100644 --- 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(); } diff --git a/progsvm.h b/progsvm.h index 4c6a7f4d..1f8e478f 100644 --- 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); diff --git a/prvm_exec.c b/prvm_exec.c index f24838e5..d29aa7f5 100644 --- a/prvm_exec.c +++ b/prvm_exec.c @@ -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 /* ====================