mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-01-31 04:20:34 +00:00
Use signal handler to invoke call_terms() before exit when possible
It's not advisable to rely on atexit() to invoke SDL_Quit(), as it causes a segmentation fault on exit for the SDL2 KMSDRM driver due to a conflict with the Mesa drivers* which upstream Mesa may not elect to fix. The issue can be resolved by replacing the atexit() call with a signal handler that will interrupt the D_DoomMain() and D_DoomLoop() functions, then invoke call_terms() within the main thread before exiting. We can leave the atexit() hook intact to handle edge cases such as abnormal process exit, or exit methods which do not produce signals such as Alt+F4 or window close via GUI (neither of which are possible in a KMS context, so should not affect KMSDRM sessions). Fixes a segmentation fault/uninterruptible application hang on exit for all KMS targets, including Raspberry Pi 4B, 3B and Intel i965. * See: https://bugzilla.libsdl.org/show_bug.cgi?id=4530 and https://lists.freedesktop.org/archives/mesa-users/2019-March/001519.html
This commit is contained in:
parent
b2aa973396
commit
457dc8b5a9
3 changed files with 27 additions and 4 deletions
|
@ -260,6 +260,10 @@ cycle_t FrameCycles;
|
|||
// [SP] Store the capabilities of the renderer in a global variable, to prevent excessive per-frame processing
|
||||
uint32_t r_renderercaps = 0;
|
||||
|
||||
#ifndef _WIN32
|
||||
volatile
|
||||
#endif
|
||||
int game_running = 1;
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
|
@ -1050,7 +1054,7 @@ void D_DoomLoop ()
|
|||
|
||||
vid_cursor.Callback();
|
||||
|
||||
for (;;)
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -1107,7 +1111,7 @@ void D_DoomLoop ()
|
|||
Printf("%s", error.stacktrace.GetChars());
|
||||
D_ErrorCleanup();
|
||||
}
|
||||
}
|
||||
} while (game_running);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2839,7 +2843,8 @@ void D_DoomMain (void)
|
|||
|
||||
GC::DelSoftRootHead();
|
||||
|
||||
PClass::StaticShutdown();
|
||||
if (game_running)
|
||||
PClass::StaticShutdown();
|
||||
|
||||
GC::FullGC(); // perform one final garbage collection after shutdown
|
||||
|
||||
|
@ -2851,7 +2856,7 @@ void D_DoomMain (void)
|
|||
|
||||
gamestate = GS_STARTUP;
|
||||
}
|
||||
while (1);
|
||||
while (game_running);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -85,6 +85,8 @@ void Linux_I_FatalError(const char* errortext);
|
|||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern volatile int game_running;
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
// The command line arguments.
|
||||
|
@ -95,6 +97,9 @@ FArgs *Args;
|
|||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
void exit_handler(int dummy) {
|
||||
game_running = 0;
|
||||
}
|
||||
|
||||
static void NewFailure ()
|
||||
{
|
||||
|
@ -206,6 +211,17 @@ int main (int argc, char **argv)
|
|||
|
||||
atexit (call_terms);
|
||||
atterm (I_Quit);
|
||||
/*
|
||||
Register signal handlers to interrupt D_DoomMain and D_DoomLoop, allowing
|
||||
call_terms() to be invoked at the conclusion of the main thread/quit menu
|
||||
rather than at exit. The atexit() call can remain to handle edge cases
|
||||
where a signal cannot be intercepted, such as Alt+F4 or closing the window
|
||||
via the GUI.
|
||||
|
||||
Fixes segmentation fault on exit when using the KMSDRM SDL video driver.
|
||||
*/
|
||||
signal(SIGINT, exit_handler);
|
||||
signal(SIGTERM, exit_handler);
|
||||
|
||||
// Should we even be doing anything with progdir on Unix systems?
|
||||
char program[PATH_MAX];
|
||||
|
@ -262,5 +278,6 @@ int main (int argc, char **argv)
|
|||
call_terms ();
|
||||
throw;
|
||||
}
|
||||
call_terms();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -351,5 +351,6 @@ bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
|
|||
void ST_Endoom()
|
||||
{
|
||||
I_ShutdownJoysticks();
|
||||
call_terms();
|
||||
exit(0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue