From 694bc8eb0f5619102d878d8ebcc08d7bffaa4ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Thu, 26 Jan 2023 11:38:17 +0100 Subject: [PATCH] Fix exit behaviour We can't rely on atexit, handlers registered with it are in a hard to establish ordering relationship with destructors of static and thread-local objects. --- src/PowderToy.cpp | 21 +++++---------------- src/PowderToyFontEditor.cpp | 19 ++++--------------- src/PowderToySDL.cpp | 21 +++++++++++++++++++-- src/PowderToySDL.h | 1 + src/bson/BSON.cpp | 2 +- src/common/Platform.cpp | 17 +++++++++++++++++ src/common/Platform.h | 4 ++++ src/common/PlatformPosix.cpp | 2 +- src/common/PlatformWindows.cpp | 4 ++-- src/lua/LuaScriptInterface.cpp | 8 ++++++++ 10 files changed, 62 insertions(+), 37 deletions(-) diff --git a/src/PowderToy.cpp b/src/PowderToy.cpp index ce66238cf..41ed8dde5 100644 --- a/src/PowderToy.cpp +++ b/src/PowderToy.cpp @@ -123,7 +123,7 @@ void BlueScreen(String detailMessage) { while (SDL_PollEvent(&event)) if(event.type == SDL_QUIT) - exit(-1); + exit(-1); // Don't use Platform::Exit, we're practically zombies at this point anyway. blit(engine.g->vid); } } @@ -181,21 +181,9 @@ static std::unique_ptr explicitSingletons; int main(int argc, char * argv[]) { Platform::SetupCrt(); - atexit([]() { - ui::Engine::Ref().CloseWindow(); + Platform::Atexit([]() { + SDLClose(); explicitSingletons.reset(); - if (SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_OPENGL) - { - // * nvidia-460 egl registers callbacks with x11 that end up being called - // after egl is unloaded unless we grab it here and release it after - // sdl closes the display. this is an nvidia driver weirdness but - // technically an sdl bug. glfw has this fixed: - // https://github.com/glfw/glfw/commit/9e6c0c747be838d1f3dc38c2924a47a42416c081 - SDL_GL_LoadLibrary(NULL); - SDL_QuitSubSystem(SDL_INIT_VIDEO); - SDL_GL_UnloadLibrary(); - } - SDL_Quit(); }); explicitSingletons = std::make_unique(); @@ -318,7 +306,7 @@ int main(int argc, char * argv[]) FILE *new_stderr = freopen("stderr.log", "w", stderr); if (!new_stdout || !new_stderr) { - exit(42); + Platform::Exit(42); } } @@ -522,5 +510,6 @@ int main(int argc, char * argv[]) { wrapWithBluescreen(); } + Platform::Exit(0); return 0; } diff --git a/src/PowderToyFontEditor.cpp b/src/PowderToyFontEditor.cpp index 3b3b68b30..30aa626db 100644 --- a/src/PowderToyFontEditor.cpp +++ b/src/PowderToyFontEditor.cpp @@ -36,21 +36,9 @@ static std::unique_ptr explicitSingletons; int main(int argc, char * argv[]) { Platform::SetupCrt(); - atexit([]() { - ui::Engine::Ref().CloseWindow(); + Platform::Atexit([]() { + SDLClose(); explicitSingletons.reset(); - if (SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_OPENGL) - { - // * nvidia-460 egl registers callbacks with x11 that end up being called - // after egl is unloaded unless we grab it here and release it after - // sdl closes the display. this is an nvidia driver weirdness but - // technically an sdl bug. glfw has this fixed: - // https://github.com/glfw/glfw/commit/9e6c0c747be838d1f3dc38c2924a47a42416c081 - SDL_GL_LoadLibrary(NULL); - SDL_QuitSubSystem(SDL_INIT_VIDEO); - SDL_GL_UnloadLibrary(); - } - SDL_Quit(); }); explicitSingletons = std::make_unique(); @@ -99,9 +87,10 @@ int main(int argc, char * argv[]) else { std::cerr << "path to font.cpp not supplied" << std::endl; - exit(1); + Platform::Exit(1); } EngineProcess(); + Platform::Exit(0); return 0; } diff --git a/src/PowderToySDL.cpp b/src/PowderToySDL.cpp index 67ae73109..3c7593f66 100644 --- a/src/PowderToySDL.cpp +++ b/src/PowderToySDL.cpp @@ -4,6 +4,7 @@ #include "Config.h" #include "gui/interface/Engine.h" #include "graphics/Graphics.h" +#include "common/Platform.h" #include int desktopWidth = 1280; @@ -96,13 +97,13 @@ void SDLOpen() if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Initializing SDL (video subsystem): %s\n", SDL_GetError()); - exit(-1); + Platform::Exit(-1); } if (!RecreateWindow()) { fprintf(stderr, "Creating SDL window: %s\n", SDL_GetError()); - exit(-1); + Platform::Exit(-1); } int displayIndex = SDL_GetWindowDisplayIndex(sdl_window); @@ -122,6 +123,22 @@ void SDLOpen() } } +void SDLClose() +{ + if (SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_OPENGL) + { + // * nvidia-460 egl registers callbacks with x11 that end up being called + // after egl is unloaded unless we grab it here and release it after + // sdl closes the display. this is an nvidia driver weirdness but + // technically an sdl bug. glfw has this fixed: + // https://github.com/glfw/glfw/commit/9e6c0c747be838d1f3dc38c2924a47a42416c081 + SDL_GL_LoadLibrary(NULL); + SDL_QuitSubSystem(SDL_INIT_VIDEO); + SDL_GL_UnloadLibrary(); + } + SDL_Quit(); +} + void SDLSetScreen(int scale_, bool resizable_, bool fullscreen_, bool altFullscreen_, bool forceIntegerScaling_) { // bool changingScale = scale != scale_; diff --git a/src/PowderToySDL.h b/src/PowderToySDL.h index c3e5eadd1..3c7b66508 100644 --- a/src/PowderToySDL.h +++ b/src/PowderToySDL.h @@ -37,6 +37,7 @@ unsigned int GetTicks(); void CalculateMousePosition(int *x, int *y); void blit(pixel *vid); void SDLOpen(); +void SDLClose(); void SDLSetScreen(int scale_, bool resizable_, bool fullscreen_, bool altFullscreen_, bool forceIntegerScaling_); bool RecreateWindow(); void LoadWindowPosition(); diff --git a/src/bson/BSON.cpp b/src/bson/BSON.cpp index d4d16b0ef..608249d17 100644 --- a/src/bson/BSON.cpp +++ b/src/bson/BSON.cpp @@ -975,7 +975,7 @@ void bson_fatal_msg( int ok , const char *msg ) { } bson_errprintf( "error: %s\n" , msg ); - exit( -5 ); + abort(); } diff --git a/src/common/Platform.cpp b/src/common/Platform.cpp index 55f4b1242..a97a33852 100644 --- a/src/common/Platform.cpp +++ b/src/common/Platform.cpp @@ -3,6 +3,7 @@ #include "tpt-rand.h" #include "Config.h" #include +#include #include #include #include @@ -106,4 +107,20 @@ bool WriteFile(const std::vector &fileData, ByteString filename) } return true; } + +std::list exitFuncs; + +void Atexit(ExitFunc exitFunc) +{ + exitFuncs.push_front(exitFunc); +} + +void Exit(int code) +{ + for (auto exitFunc : exitFuncs) + { + exitFunc(); + } + exit(code); +} } diff --git a/src/common/Platform.h b/src/common/Platform.h index 884aa079d..8940d9102 100644 --- a/src/common/Platform.h +++ b/src/common/Platform.h @@ -55,4 +55,8 @@ namespace Platform void UpdateCleanup(); void SetupCrt(); + + using ExitFunc = void (*)(); + void Atexit(ExitFunc exitFunc); + void Exit(int code); } diff --git a/src/common/PlatformPosix.cpp b/src/common/PlatformPosix.cpp index 23fdbc5ab..46358e076 100644 --- a/src/common/PlatformPosix.cpp +++ b/src/common/PlatformPosix.cpp @@ -149,7 +149,7 @@ void DoRestart() { fprintf(stderr, "cannot restart: no executable name???\n"); } - exit(-1); + Exit(-1); } bool UpdateStart(const std::vector &data) diff --git a/src/common/PlatformWindows.cpp b/src/common/PlatformWindows.cpp index 358b370d9..80014b15d 100644 --- a/src/common/PlatformWindows.cpp +++ b/src/common/PlatformWindows.cpp @@ -209,14 +209,14 @@ void DoRestart() } else { - exit(0); + Exit(0); } } else { fprintf(stderr, "cannot restart: no executable name???\n"); } - exit(-1); + Exit(-1); } bool CanUpdate() diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index 1ff2d9f2f..0d841cd86 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -212,6 +212,14 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m): initHttpAPI(); initSocketAPI(); + lua_getglobal(l, "os"); + lua_pushcfunction(l, [](lua_State *l) -> int { + Platform::Exit(luaL_optinteger(l, 1, 0)); + return 0; + }); + lua_setfield(l, -2, "exit"); + lua_pop(l, 1); + initBZ2API(l); //Old TPT API