nix: Fork before game code and wait to catch signals and coredumps

Ditched signal_handler to avoid worrying about async-signal-safe functions.
D_QuitNetGame is not called, so players whose programs are interrupted by a
signal will time out from the server. Because the game runs in a child process,
the window can close before the "Signal Caught" text box appears.

"(core dumped)" is also included in the message if core dumping could be
determined.
This commit is contained in:
James R 2019-12-11 23:46:57 -08:00
parent 3cd5b3a33e
commit 2b837726eb
4 changed files with 87 additions and 6 deletions

View File

@ -136,6 +136,10 @@
#define LOGMESSAGES // write message in log.txt
#endif
#if (defined (__unix__) && !defined (_MSDOS)) || defined (UNIXCOMMON)
#define NEWSIGNALHANDLER
#endif
#ifdef LOGMESSAGES
extern FILE *logstream;
#endif

View File

@ -92,6 +92,10 @@ ticcmd_t *I_BaseTiccmd4(void);
*/
void I_Quit(void) FUNCNORETURN;
/** \brief Print a message and text box about a signal that was raised.
*/
void I_ReportSignal(int num, int coredumped);
typedef enum
{
EvilForce = -1,

View File

@ -26,6 +26,11 @@
#include <unistd.h>
#endif
#ifdef NEWSIGNALHANDLER
#include <errno.h>
#include <sys/wait.h>
#endif
#ifdef HAVE_SDL
#ifdef HAVE_TTF
@ -157,6 +162,53 @@ int main(int argc, char **argv)
#endif
MakeCodeWritable();
#endif
#ifdef NEWSIGNALHANDLER
switch (fork())
{
case -1:
I_Error(
"Error setting up signal reporting: fork(): %s\n",
strerror(errno)
);
break;
case 0:
break;
default:
{
int status;
int signum;
if (wait(&status) == -1)
{
I_Error(
"Error setting up signal reporting: fork(): %s\n",
strerror(errno)
);
}
else
{
if (WIFSIGNALED (status))
{
signum = WTERMSIG (status);
#ifdef WCOREDUMP
I_ReportSignal(signum, WCOREDUMP (status));
#else
I_ReportSignal(signum, 0);
#endif
status = 128 + signum;
}
else if (WIFEXITED (status))
{
status = WEXITSTATUS (status);
}
I_ShutdownSystem();
exit(status);
}
}
}
#endif/*NEWSIGNALHANDLER*/
// startup SRB2
CONS_Printf("Setting up SRB2Kart...\n");
D_SRB2Main();

View File

@ -246,13 +246,11 @@ SDL_bool framebuffer = SDL_FALSE;
UINT8 keyboard_started = false;
FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num)
void I_ReportSignal(int num, int coredumped)
{
//static char msg[] = "oh no! back to reality!\r\n";
const char * sigmsg;
char sigdef[32];
D_QuitNetGame(); // Fix server freezes
char msg[128];
switch (num)
{
@ -278,8 +276,21 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num)
sigmsg = "SIGABRT - abnormal termination triggered by abort call";
break;
default:
sprintf(sigdef,"signal number %d", num);
sigmsg = sigdef;
sprintf(msg,"signal number %d", num);
if (coredumped)
sigmsg = 0;
else
sigmsg = msg;
}
if (coredumped)
{
if (sigmsg)
sprintf(msg, "%s (core dumped)", sigmsg);
else
strcat(msg, " (core dumped)");
sigmsg = msg;
}
I_OutputMsg("\nsignal_handler() error: %s\n", sigmsg);
@ -287,11 +298,19 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num)
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
"Signal caught",
sigmsg, NULL);
}
#ifndef NEWSIGNALHANDLER
FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num)
{
D_QuitNetGame(); // Fix server freezes
I_ReportSignal(num, 0);
I_ShutdownSystem();
signal(num, SIG_DFL); //default signal action
raise(num);
I_Quit();
}
#endif
FUNCNORETURN static ATTRNORETURN void quit_handler(int num)
{
@ -681,10 +700,12 @@ void I_StartupKeyboard (void)
// If these defines don't exist,
// then compilation would have failed above us...
#ifndef NEWSIGNALHANDLER
signal(SIGILL , signal_handler);
signal(SIGSEGV , signal_handler);
signal(SIGABRT , signal_handler);
signal(SIGFPE , signal_handler);
#endif
}
//