diff options
-rw-r--r-- | inc/common/common.h | 3 | ||||
-rw-r--r-- | src/common/common.c | 12 | ||||
-rw-r--r-- | src/refresh/images.c | 5 | ||||
-rw-r--r-- | src/server/commands.c | 14 | ||||
-rw-r--r-- | src/server/init.c | 3 | ||||
-rw-r--r-- | src/server/mvd/client.c | 1 | ||||
-rw-r--r-- | src/server/mvd/game.c | 1 | ||||
-rw-r--r-- | src/server/save.c | 24 |
8 files changed, 44 insertions, 19 deletions
diff --git a/inc/common/common.h b/inc/common/common.h index 58aafa7..48e5e45 100644 --- a/inc/common/common.h +++ b/inc/common/common.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/cmd.h" #include "common/utils.h" +#include <setjmp.h> // // common.h -- definitions common between client and server, but not game.dll @@ -171,6 +172,8 @@ extern unsigned time_before_ref; extern unsigned time_after_ref; #endif +extern jmp_buf com_abortframe; + extern const char com_version_string[]; extern unsigned com_framenum; diff --git a/src/common/common.c b/src/common/common.c index 31ea3fc..7a0e713 100644 --- a/src/common/common.c +++ b/src/common/common.c @@ -49,9 +49,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "server/server.h" #include "system/system.h" -#include <setjmp.h> - -static jmp_buf abortframe; // an ERR_DROP occured, exit the entire frame +jmp_buf com_abortframe; // an ERR_DROP occured, exit the entire frame static qboolean com_errorEntered; static char com_errorMsg[MAXERRORMSG]; // from Com_Printf/Com_Error @@ -561,13 +559,13 @@ abort: FS_Flush(com_logFile); } com_errorEntered = qfalse; - longjmp(abortframe, -1); + longjmp(com_abortframe, -1); } #ifdef _WIN32 void Com_AbortFrame(void) { - longjmp(abortframe, -1); + longjmp(com_abortframe, -1); } #endif @@ -865,7 +863,7 @@ Qcommon_Init */ void Qcommon_Init(int argc, char **argv) { - if (setjmp(abortframe)) + if (setjmp(com_abortframe)) Sys_Error("Error during initialization: %s", com_errorMsg); com_argc = argc; @@ -1048,7 +1046,7 @@ void Qcommon_Frame(void) static unsigned remaining; static float frac; - if (setjmp(abortframe)) { + if (setjmp(com_abortframe)) { return; // an ERR_DROP was thrown } diff --git a/src/refresh/images.c b/src/refresh/images.c index 315e506..bb017e4 100644 --- a/src/refresh/images.c +++ b/src/refresh/images.c @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "format/wal.h" #if USE_PNG +#define PNG_SKIP_SETJMP_CHECK #include <png.h> #if USE_ZLIB #include <zlib.h> @@ -40,10 +41,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <jpeglib.h> #endif -#if USE_PNG || USE_JPG -#include <setjmp.h> -#endif - #define IMG_LOAD(x) \ static qerror_t IMG_Load##x(byte *rawdata, size_t rawlen, \ const char *filename, byte **pic, int *width, int *height) diff --git a/src/server/commands.c b/src/server/commands.c index 146c6de..30df491 100644 --- a/src/server/commands.c +++ b/src/server/commands.c @@ -261,6 +261,7 @@ static void SV_Map(qboolean restart) { mapcmd_t cmd; size_t len; + jmp_buf tmp; memset(&cmd, 0, sizeof(cmd)); @@ -274,6 +275,16 @@ static void SV_Map(qboolean restart) if (!SV_ParseMapCmd(&cmd)) return; + // save error frame + memcpy(tmp, com_abortframe, sizeof(jmp_buf)); + + // catch ERR_DROP and free the map + if (setjmp(com_abortframe)) { + memcpy(com_abortframe, tmp, sizeof(jmp_buf)); + CM_FreeMap(&cmd.cm); + return; + } + // wipe savegames cmd.endofunit |= restart; @@ -283,6 +294,9 @@ static void SV_Map(qboolean restart) if ((sv.state != ss_game && sv.state != ss_pic) || restart) SV_InitGame(MVD_SPAWN_DISABLED); // the game is just starting + // restore error frame + memcpy(com_abortframe, tmp, sizeof(jmp_buf)); + SV_SpawnServer(&cmd); SV_AutoSaveEnd(); diff --git a/src/server/init.c b/src/server/init.c index 3afa907..f477a12 100644 --- a/src/server/init.c +++ b/src/server/init.c @@ -182,8 +182,7 @@ void SV_SpawnServer(mapcmd_t *cmd) Q_strlcpy(sv.mapcmd, cmd->buffer, sizeof(sv.mapcmd)); if (Cvar_VariableInteger("deathmatch")) { - sprintf(sv.configstrings[CS_AIRACCEL], - "%d", sv_airaccelerate->integer); + sprintf(sv.configstrings[CS_AIRACCEL], "%d", sv_airaccelerate->integer); } else { strcpy(sv.configstrings[CS_AIRACCEL], "0"); } diff --git a/src/server/mvd/client.c b/src/server/mvd/client.c index e3c3642..0fa6968 100644 --- a/src/server/mvd/client.c +++ b/src/server/mvd/client.c @@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client.h" #include "server/mvd/protocol.h" -#include <setjmp.h> #define FOR_EACH_GTV(gtv) \ LIST_FOR_EACH(gtv_t, gtv, &mvd_gtv_list, entry) diff --git a/src/server/mvd/game.c b/src/server/mvd/game.c index 3573a73..01f443a 100644 --- a/src/server/mvd/game.c +++ b/src/server/mvd/game.c @@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc., // #include "client.h" -#include <setjmp.h> static cvar_t *mvd_admin_password; static cvar_t *mvd_part_filter; diff --git a/src/server/save.c b/src/server/save.c index 2dd1f41..2fddda7 100644 --- a/src/server/save.c +++ b/src/server/save.c @@ -309,6 +309,7 @@ static int read_server_file(void) char name[MAX_OSPATH], string[MAX_STRING_CHARS]; mapcmd_t cmd; size_t len; + jmp_buf tmp; // errors like missing file, bad version, etc are // non-fatal and just return to the command handler @@ -341,6 +342,16 @@ static int read_server_file(void) if (!SV_ParseMapCmd(&cmd)) return -1; + // save error frame + memcpy(tmp, com_abortframe, sizeof(jmp_buf)); + + // catch ERR_DROP and free the map + if (setjmp(com_abortframe)) { + memcpy(com_abortframe, tmp, sizeof(jmp_buf)); + CM_FreeMap(&cmd.cm); + return -1; + } + // any error will drop from this point SV_Shutdown("Server restarted\n", ERR_RECONNECT); @@ -378,6 +389,9 @@ static int read_server_file(void) ge->ReadGame(name); + // restore error frame + memcpy(com_abortframe, tmp, sizeof(jmp_buf)); + // go to the map SV_SpawnServer(&cmd); return 0; @@ -402,6 +416,8 @@ static int read_level_file(void) if (MSG_ReadLong() != SAVE_VERSION) return -1; + // any error will drop from this point + // the rest can't underflow msg_read.allowunderflow = qfalse; @@ -412,17 +428,17 @@ static int read_level_file(void) break; if (index < 0 || index > MAX_CONFIGSTRINGS) - return -1; + Com_Error(ERR_DROP, "Bad savegame configstring index"); maxlen = CS_SIZE(index); len = MSG_ReadString(sv.configstrings[index], maxlen); if (len >= maxlen) - return -1; + Com_Error(ERR_DROP, "Savegame configstring too long"); } len = MSG_ReadByte(); if (len > MAX_MAP_PORTAL_BYTES) - return -1; + Com_Error(ERR_DROP, "Savegame portalbits too long"); SV_ClearWorld(); @@ -432,7 +448,7 @@ static int read_level_file(void) len = Q_snprintf(name, MAX_OSPATH, "%s/save/" SAVE_CURRENT "/%s.sav", fs_gamedir, sv.name); if (len >= MAX_OSPATH) - return -1; + Com_Error(ERR_DROP, "Savegame path too long"); ge->ReadLevel(name); return 0; |