From 2f36ef3fb3670ee70c80cebf4b73f1cedc3d02da Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 6 Mar 2019 16:02:35 -0800 Subject: [PATCH 1/5] Add a hack to not use non-reentrant functions (like printf) while inside of signal_handler --- src/console.c | 3 +++ src/d_clisrv.c | 3 +++ src/d_net.c | 10 +++++++++- src/doomdef.h | 3 +++ src/doomtype.h | 8 ++++---- src/g_game.c | 2 +- src/i_tcp.c | 6 +++++- src/lua_script.c | 4 +--- src/m_misc.c | 2 +- src/p_setup.c | 2 +- src/sdl/i_system.c | 27 +++++++++++++++++++++++---- 11 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/console.c b/src/console.c index a10d73e7f..2e914a0fa 100644 --- a/src/console.c +++ b/src/console.c @@ -1260,6 +1260,9 @@ void CONS_Printf(const char *fmt, ...) va_list argptr; static char *txt = NULL; + if (mustbereentrant) + return; + if (txt == NULL) txt = malloc(8192); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e50b1d9de..9cd27debf 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -473,6 +473,9 @@ void D_ResetTiccmds(void) { INT32 i; + if (mustbereentrant) + return; + memset(&localcmds, 0, sizeof(ticcmd_t)); memset(&localcmds2, 0, sizeof(ticcmd_t)); memset(&localcmds3, 0, sizeof(ticcmd_t)); diff --git a/src/d_net.c b/src/d_net.c index 6702a60a4..dea0d7242 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -457,6 +457,8 @@ void Net_SendAcks(INT32 node) #ifdef NONET (void)node; #else + if (mustbereentrant) + return; netbuffer->packettype = PT_NOTHING; M_Memcpy(netbuffer->u.textcmd, nodes[node].acktosend, MAXACKTOSEND); HSendPacket(node, false, 0, MAXACKTOSEND); @@ -640,6 +642,8 @@ void Net_WaitAllAckReceived(UINT32 timeout) #ifdef NONET (void)timeout; #else + if (mustbereentrant) + return; tic_t tictac = I_GetTime(); timeout = tictac + timeout*NEWTICRATE; @@ -1039,6 +1043,8 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen doomcom->datalength = (INT16)(packetlength + BASEPACKETSIZE); if (node == 0) // Packet is to go back to us { + if (mustbereentrant) + return false; if ((rebound_head+1) % MAXREBOUND == rebound_tail) { #ifdef PARANOIA @@ -1146,6 +1152,8 @@ boolean HGetPacket(void) // Get a packet from self if (rebound_tail != rebound_head) { + if (mustbereentrant) + return false; M_Memcpy(netbuffer, &reboundstore[rebound_tail], reboundsize[rebound_tail]); doomcom->datalength = reboundsize[rebound_tail]; if (netbuffer->packettype == PT_NODETIMEOUT) @@ -1235,7 +1243,7 @@ static boolean Internal_Get(void) return false; } -FUNCNORETURN static ATTRNORETURN void Internal_Send(void) +static void Internal_Send(void) { I_Error("Send without netgame\n"); } diff --git a/src/doomdef.h b/src/doomdef.h index ab863c6f6..ffba75c4e 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -585,4 +585,7 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP +// You must use reentrant functions. This is a big hack for now, though. +extern boolean mustbereentrant; + #endif // __DOOMDEF__ diff --git a/src/doomtype.h b/src/doomtype.h index 5d6434845..5d74274bb 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -259,20 +259,20 @@ size_t strlcpy(char *dst, const char *src, size_t siz); #elif (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) // >= GCC 4.4 #define FUNCPRINTF __attribute__ ((format(ms_printf, 1, 2))) #define FUNCDEBUG __attribute__ ((format(ms_printf, 2, 3))) - #define FUNCIERROR __attribute__ ((format(ms_printf, 1, 2),noreturn)) + #define FUNCIERROR __attribute__ ((format(ms_printf, 1, 2),/*noreturn*/)) #else #define FUNCPRINTF __attribute__ ((format(printf, 1, 2))) #define FUNCDEBUG __attribute__ ((format(printf, 2, 3))) - #define FUNCIERROR __attribute__ ((format(printf, 1, 2),noreturn)) + #define FUNCIERROR __attribute__ ((format(printf, 1, 2),/*noreturn*/)) #endif #else #define FUNCPRINTF __attribute__ ((format(printf, 1, 2))) #define FUNCDEBUG __attribute__ ((format(printf, 2, 3))) - #define FUNCIERROR __attribute__ ((format(printf, 1, 2),noreturn)) + #define FUNCIERROR __attribute__ ((format(printf, 1, 2),/*noreturn*/)) #endif #ifndef FUNCIERROR - #define FUNCIERROR __attribute__ ((noreturn)) + #define FUNCIERROR __attribute__ ((/*noreturn*/)) #endif #define FUNCMATH __attribute__((const)) diff --git a/src/g_game.c b/src/g_game.c index f0d221ff6..2f82687bd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6423,7 +6423,7 @@ void G_StopMetalDemo(void) } // Stops metal sonic recording. -ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void) +void G_StopMetalRecording(void) { boolean saved = false; if (demo_p) diff --git a/src/i_tcp.c b/src/i_tcp.c index f8a65b754..f6297ed27 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -418,6 +418,9 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) #ifdef HAVE_NTOP void *addr; + if (mustbereentrant) + return NULL; + if(sk->any.sa_family == AF_INET) addr = &sk->ip4.sin_addr; #ifdef HAVE_IPV6 @@ -790,7 +793,8 @@ static void SOCK_FreeNodenum(INT32 numnode) nodesocket[numnode] = ERRSOCKET; // put invalid address - memset(&clientaddress[numnode], 0, sizeof (clientaddress[numnode])); + if (!mustbereentrant) + memset(&clientaddress[numnode], 0, sizeof (clientaddress[numnode])); } #endif diff --git a/src/lua_script.c b/src/lua_script.c index 1f87d33ee..77a3fd4d0 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -70,13 +70,11 @@ static void *LUA_Alloc(void *ud, void *ptr, size_t osize, size_t nsize) // Panic function Lua calls when there's an unprotected error. // This function cannot return. Lua would kill the application anyway if it did. -FUNCNORETURN static int LUA_Panic(lua_State *L) +static int LUA_Panic(lua_State *L) { CONS_Alert(CONS_ERROR,"LUA PANIC! %s\n",lua_tostring(L,-1)); I_Error("An unfortunate Lua processing error occurred in the exe itself. This is not a scripting error on your part."); -#ifndef __GNUC__ return -1; -#endif } // This function decides which global variables you are allowed to set. diff --git a/src/m_misc.c b/src/m_misc.c index c95aa392c..2be1ee558 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -643,7 +643,7 @@ static const char *Newsnapshotfile(const char *pathname, const char *ext) #endif #ifdef HAVE_PNG -FUNCNORETURN static void PNG_error(png_structp PNG, png_const_charp pngtext) +static void PNG_error(png_structp PNG, png_const_charp pngtext) { //CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext); I_Error("libpng error at %p: %s", PNG, pngtext); diff --git a/src/p_setup.c b/src/p_setup.c index 1acfb7a32..b206b2314 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -152,7 +152,7 @@ mapthing_t *redctfstarts[MAXPLAYERS]; * not be called log.txt. * \sa CON_LogMessage, I_Error */ -FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg) +static void CorruptMapError(const char *msg) { // don't use va() because the calling function probably uses it char mapnum[10]; diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index f92f1f14a..3aed1baea 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -246,14 +246,24 @@ SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; -FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) +/* +I hope you know that you can only call reentrant functions in signal handlers. +If your function doesn't do that, check here that false before you do anything. +*/ +boolean mustbereentrant = false; + +static void signal_handler(INT32 num) { //static char msg[] = "oh no! back to reality!\r\n"; - const char * sigmsg; - char sigdef[32]; + //const char * sigmsg; + //char sigdef[32]; + + mustbereentrant = true;/* and we about to die anyway */ D_QuitNetGame(); // Fix server freezes + /* nixed cause it's fucked!!!! */ +#if 0 switch (num) { // case SIGINT: @@ -288,9 +298,11 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) "Signal caught", sigmsg, NULL); I_ShutdownSystem(); +#endif signal(num, SIG_DFL); //default signal action raise(num); - I_Quit(); + //I_Quit(); + mustbereentrant = false;/* ytho */ } FUNCNORETURN static ATTRNORETURN void quit_handler(int num) @@ -3118,6 +3130,13 @@ void I_Error(const char *error, ...) va_list argptr; char buffer[8192]; + /* + For now; there's a way to print from within + signal handlers, but you're not going to like it! + */ + if (mustbereentrant) + return; + // recursive error detecting if (shutdowning) { From 3b0f151818077ea358b1058a9413ab1fa8cbb06e Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 6 Mar 2019 18:16:34 -0800 Subject: [PATCH 2/5] Return where I_Error would do so --- src/g_game.h | 2 +- src/p_slopes.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/g_game.h b/src/g_game.h index fc7a4a4f5..ebc44b15e 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -190,7 +190,7 @@ void G_UpdateStaffGhostName(lumpnum_t l); void G_DoPlayMetal(void); void G_DoneLevelLoad(void); void G_StopMetalDemo(void); -ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); +void G_StopMetalRecording(void); void G_StopDemo(void); boolean G_CheckDemoStatus(void); diff --git a/src/p_slopes.c b/src/p_slopes.c index c6416b75a..276f9f1fc 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -143,6 +143,7 @@ void P_RunDynamicSlopes(void) { default: I_Error("P_RunDynamicSlopes: slope has invalid type!"); + return; } if (slope->zdelta != FixedDiv(zdelta, slope->extent)) { From dde938f91ef8aab9dc6d8d9b14edea8bfa82dda6 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 6 Mar 2019 18:16:48 -0800 Subject: [PATCH 3/5] Don't mix code --- src/d_net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/d_net.c b/src/d_net.c index dea0d7242..58d1c2773 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -642,9 +642,10 @@ void Net_WaitAllAckReceived(UINT32 timeout) #ifdef NONET (void)timeout; #else + tic_t tictac; if (mustbereentrant) return; - tic_t tictac = I_GetTime(); + tictac = I_GetTime(); timeout = tictac + timeout*NEWTICRATE; HGetPacket(); From 0bdb0e5ef179242f82ab03eda5c2cae91f24cac2 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 13 Mar 2019 23:51:45 -0700 Subject: [PATCH 4/5] Support signal printing with fork --- src/sdl/i_main.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ src/sdl/i_system.c | 26 ++++++++++----------- 2 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index 41a9d7cd6..7e812590a 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -26,6 +26,13 @@ #include #endif +#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) +#include + +#include +#include +#endif + #ifdef HAVE_SDL #ifdef HAVE_TTF @@ -96,6 +103,8 @@ static inline VOID MakeCodeWritable(VOID) #endif +extern void I_ReportSignal(INT32); + /** \brief The main function \param argc number of arg @@ -117,6 +126,12 @@ int main(int argc, char **argv) myargc = argc; myargv = argv; /// \todo pull out path to exe from this string +#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) + /* child info */ + pid_t cpid; + int cstatus; +#endif + #ifdef HAVE_TTF #ifdef _WIN32 I_StartupTTF(FONTPOINTSIZE, SDL_INIT_VIDEO|SDL_INIT_AUDIO, SDL_SWSURFACE); @@ -138,6 +153,47 @@ int main(int argc, char **argv) //I_OutputMsg("I_StartupSystem() ...\n"); I_StartupSystem(); + +#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) + /* + Now we can fork into a child process and do actual work while the parent + waits for him to exit. Then we check for a signal termination and report + signals that way--the PROPER WAY. Yesh + */ + if (( cpid = fork() ) == -1) + { + I_OutputMsg("Error when setting up signal reporting: fork(): %s\n", + strerror(errno)); + } + else + { + if (cpid != 0)/* we are the parent */ + { + if (waitpid(cpid, &cstatus, 0) == -1) + { + I_OutputMsg("Error when setting up signal reporting: waitpid(): %s\n", + strerror(errno)); + } + else + { + if (WIFSIGNALED(cstatus)) + { + I_ReportSignal(WTERMSIG(cstatus)); + I_Quit(); + if (WIFEXITED(cstatus)) + exit(WEXITSTATUS(cstatus)); + else + exit(EXIT_FAILURE); + } + if (WIFEXITED(cstatus)) + exit(WEXITSTATUS(cstatus)); + else + exit(EXIT_SUCCESS); + } + } + } +#endif + #if defined (_WIN32) { #if 0 // just load the DLL diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 3aed1baea..74de0a6fe 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -252,18 +252,10 @@ If your function doesn't do that, check here that false before you do anything. */ boolean mustbereentrant = false; -static void signal_handler(INT32 num) +void I_ReportSignal(INT32 num) { - //static char msg[] = "oh no! back to reality!\r\n"; - //const char * sigmsg; - //char sigdef[32]; - - mustbereentrant = true;/* and we about to die anyway */ - - D_QuitNetGame(); // Fix server freezes - - /* nixed cause it's fucked!!!! */ -#if 0 + const char * sigmsg; + char sigdef[32]; switch (num) { // case SIGINT: @@ -297,11 +289,17 @@ static void signal_handler(INT32 num) SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Signal caught", sigmsg, NULL); - I_ShutdownSystem(); -#endif +} + +static void signal_handler(INT32 num) +{ + mustbereentrant = true;/* and we about to die anyway */ + + D_QuitNetGame(); // Fix server freezes + signal(num, SIG_DFL); //default signal action raise(num); - //I_Quit(); + mustbereentrant = false;/* ytho */ } From 5fe783c8b4be27f5b901659e0ee78fd6a96cb599 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 14 Mar 2019 15:21:31 -0700 Subject: [PATCH 5/5] Attempt to support natural program status dialogue on Windows --- src/sdl/i_system.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 74de0a6fe..9b4e2c153 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -297,8 +297,13 @@ static void signal_handler(INT32 num) D_QuitNetGame(); // Fix server freezes + /* + On Windows raising a signal seems to disable a dialogue box from showing. + */ +#ifndef _WIN32 signal(num, SIG_DFL); //default signal action raise(num); +#endif mustbereentrant = false;/* ytho */ }