From e71f6fcc8575de98edbadb13f4ecfc2013297154 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Tue, 2 Jan 2024 13:18:31 -0600 Subject: [PATCH] Add evil mutex bypass hack in console Fixes KartKrew/Kart#795 --- src/console.c | 8 ++++++-- src/i_system.h | 3 +++ src/sdl/i_system.cpp | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/console.c b/src/console.c index dd24ffaf0..4d45dc07c 100644 --- a/src/console.c +++ b/src/console.c @@ -44,8 +44,12 @@ #ifdef HAVE_THREADS I_mutex con_mutex; -# define Lock_state() I_lock_mutex(&con_mutex) -# define Unlock_state() I_unlock_mutex(con_mutex) +// g_in_exiting_signal_handler is an evil hack +// to avoid infinite SIGABRT recursion in the signal handler +// due to poisoned locks or mach-o kernel not supporting locks in signals +// or something like that. idk +# define Lock_state() if (!g_in_exiting_signal_handler) { I_lock_mutex(&con_mutex); } +# define Unlock_state() if (!g_in_exiting_signal_handler) { I_unlock_mutex(con_mutex); } #else/*HAVE_THREADS*/ # define Lock_state() # define Unlock_state() diff --git a/src/i_system.h b/src/i_system.h index f9161ece0..74dc85ea1 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -38,6 +38,9 @@ extern UINT8 graphics_started; */ extern UINT8 keyboard_started; +/** \brief Set to true when inside a signal handler that will exit the program. */ +extern boolean g_in_exiting_signal_handler; + /** \brief The I_GetFreeMem function \param total total memory in the system diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 2a1a4f9ee..0fba83218 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -208,6 +208,7 @@ SDL_bool consolevent = SDL_FALSE; SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; +boolean g_in_exiting_signal_handler = false; #ifdef UNIXBACKTRACE #define STDERR_WRITE(string) if (fd != -1) I_OutputMsg("%s", string) @@ -428,6 +429,8 @@ static void I_ReportSignal(int num, int coredumped) #ifndef NEWSIGNALHANDLER FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { + g_in_exiting_signal_handler = true; + if (g_main_thread_id != std::this_thread::get_id()) { // Do not attempt any sort of recovery if this signal triggers off the main thread