Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let signal handler do its thing #7

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 3 additions & 0 deletions src/d_clisrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
13 changes: 11 additions & 2 deletions src/d_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -640,7 +642,10 @@ void Net_WaitAllAckReceived(UINT32 timeout)
#ifdef NONET
(void)timeout;
#else
tic_t tictac = I_GetTime();
tic_t tictac;
if (mustbereentrant)
return;
tictac = I_GetTime();
timeout = tictac + timeout*NEWTICRATE;

HGetPacket();
Expand Down Expand Up @@ -1039,6 +1044,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
Expand Down Expand Up @@ -1146,6 +1153,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)
Expand Down Expand Up @@ -1235,7 +1244,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");
}
Expand Down
3 changes: 3 additions & 0 deletions src/doomdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__
8 changes: 4 additions & 4 deletions src/doomtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion src/g_game.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/g_game.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
6 changes: 5 additions & 1 deletion src/i_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
4 changes: 1 addition & 3 deletions src/lua_script.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/m_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/p_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
1 change: 1 addition & 0 deletions src/p_slopes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
56 changes: 56 additions & 0 deletions src/sdl/i_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@
#include <unistd.h>
#endif

#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
#include <errno.h>

#include <unistd.h>
#include <sys/wait.h>
#endif

#ifdef HAVE_SDL

#ifdef HAVE_TTF
Expand Down Expand Up @@ -96,6 +103,8 @@ static inline VOID MakeCodeWritable(VOID)
#endif


extern void I_ReportSignal(INT32);

/** \brief The main function

\param argc number of arg
Expand All @@ -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);
Expand All @@ -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
Expand Down
36 changes: 29 additions & 7 deletions src/sdl/i_system.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,14 +246,16 @@ 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;

void I_ReportSignal(INT32 num)
{
//static char msg[] = "oh no! back to reality!\r\n";
const char * sigmsg;
char sigdef[32];

D_QuitNetGame(); // Fix server freezes

switch (num)
{
// case SIGINT:
Expand Down Expand Up @@ -287,10 +289,23 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num)
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
"Signal caught",
sigmsg, NULL);
I_ShutdownSystem();
}

static void signal_handler(INT32 num)
{
mustbereentrant = true;/* and we about to die anyway */

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);
I_Quit();
#endif

mustbereentrant = false;/* ytho */
}

FUNCNORETURN static ATTRNORETURN void quit_handler(int num)
Expand Down Expand Up @@ -3118,6 +3133,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)
{
Expand Down