From 90e493fa3a7fee51123078d02f988fa6d1f07a84 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 9 Jan 2025 20:26:14 +0300 Subject: [PATCH] engine: common: add Host_ExitInMain function that will force engine return from Host_Main() function, essentially making engine gracefully exit on Android In future, this might be used everywhere, so users would be able to add custom cleanup in some advanced game_launch implementation, on any platform. --- engine/common/common.h | 1 + engine/common/host.c | 26 ++++++++++++++++++++++++++ engine/common/system.c | 10 ++++++++++ 3 files changed, 37 insertions(+) diff --git a/engine/common/common.h b/engine/common/common.h index 4a3066b6..95af6384 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -559,6 +559,7 @@ void Host_Error( const char *error, ... ) FORMAT_CHECK( 1 ); void Host_ValidateEngineFeatures( uint32_t mask, uint32_t features ); void Host_Frame( double time ); void Host_Credits( void ); +void Host_ExitInMain( void ); // // host_state.c diff --git a/engine/common/host.c b/engine/common/host.c index c4d814cf..0c9847a2 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -43,6 +43,27 @@ GNU General Public License for more details. static pfnChangeGame pChangeGame = NULL; host_parm_t host; // host parms +#if XASH_ANDROID +static jmp_buf return_from_main_buf; + +/* +=============== +Host_ExitInMain + +On some platforms (e.g. Android) we can't exit with exit(3) as calling it would +kill wrapper process (e.g. app_process) too early, before all resources would +be freed, contexts released, files closed, etc, etc... + +To fix this, we create jmp_buf in Host_Main function, when jumping into with +non-zero value will immediately return from it with `error_on_exit`. +=============== +*/ +void Host_ExitInMain( void ) +{ + longjmp( return_from_main_buf, 1 ); +} +#endif // XASH_ANDROID + #ifdef XASH_ENGINE_TESTS struct tests_stats_s tests_stats; #endif @@ -1319,6 +1340,11 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa // check after all configs were executed HPAK_CheckIntegrity( hpk_custom_file.string ); +#if XASH_ANDROID + if( setjmp( return_from_main_buf )) + return error_on_exit; +#endif // XASH_ANDROID + // main window message loop while( !host.crashed ) { diff --git a/engine/common/system.c b/engine/common/system.c index 46cf816c..765a4d26 100644 --- a/engine/common/system.c +++ b/engine/common/system.c @@ -420,6 +420,12 @@ void Sys_Error( const char *error, ... ) _exit->_Exit->asm._exit->_exit As we do not need atexit(), just throw hidden exception */ + +// Hey, you, making an Emscripten port! +// What if we're not supposed to use exit() on Emscripten and instead we should +// exit from the main() function? Would this fix this bug? Test this case, pls. +#error "Read the comment above" + #include #define exit my_exit void my_exit(int ret) @@ -438,7 +444,11 @@ Sys_Quit void Sys_Quit( const char *reason ) { Host_ShutdownWithReason( reason ); +#if XASH_ANDROID + Host_ExitInMain(); +#else exit( error_on_exit ); +#endif } /*