system: flush logs and _Exit on quit for macOS and Linux instead of tearing down under live guest threads

This commit is contained in:
mchughalex 2026-07-21 10:33:27 +01:00
parent f3089c790f
commit 705b78f53e
4 changed files with 33 additions and 7 deletions

View file

@ -71,6 +71,13 @@ void InitLoggingEarly();
*/
void ShutdownLogging();
/**
* Flush all loggers without shutting the logging system down. Safe to call
* while other threads may still be logging; intended for fast-exit paths
* that end the process with _Exit right after flushing.
*/
void FlushLogging();
/**
* Register a new log category at runtime.
*

View file

@ -292,6 +292,16 @@ void InitLogging(const char* log_file, spdlog::level::level_enum level) {
InitLogging(config);
}
void FlushLogging() {
std::lock_guard lock(g_mutex);
if (!g_initialized && !g_early_initialized)
return;
for (auto& entry : g_registry)
if (entry.logger)
entry.logger->flush();
}
void ShutdownLogging() {
std::lock_guard lock(g_mutex);
if (!g_initialized && !g_early_initialized)

View file

@ -75,5 +75,8 @@ extern "C" int main(int argc_pre_gtk, char** argv_pre_gtk) {
// Logging may still be needed in the destructors.
rex::ShutdownLogging();
return result;
// Guest threads that could not be cancelled may still be running; global
// static destruction under them can turn a clean quit into an abort or a
// nonzero exit status. Everything is flushed - end the process here.
std::_Exit(result);
}

View file

@ -46,16 +46,22 @@ int main(int argc, char** argv) {
bool initialized = app->OnInitialize();
result = initialized ? app_context.RunMainLoop() : EXIT_FAILURE;
#if REX_PLATFORM_MAC
// Skip app/runtime teardown entirely: guest threads cannot be reliably
// stopped on Darwin (pthread_cancel only lands at cancellation points,
// never in CPU-bound recompiled code), so the destructor chain races
// still-running guest threads over freed kernel objects and turns a
// normal quit into the macOS crash-reporter dialog. Flush the logs and
// leave; the OS reclaims everything else. Flush-only on purpose -
// ShutdownLogging destroys sinks a straggler thread may still be using.
rex::FlushLogging();
std::_Exit(result);
#else
app->InvokeOnDestroy();
#endif
}
rex::ShutdownLogging();
#if REX_PLATFORM_MAC
// After explicit app teardown and log flushing, avoid macOS/SDL/global static
// teardown paths that can change a clean Close Game exit into status 1.
std::_Exit(result);
#else
SDL_Quit();
#endif
return result;
}