From 395e1ce67d8f113a222888bdaadcb68b34d731ee Mon Sep 17 00:00:00 2001 From: MiTHRAL Date: Fri, 28 Aug 2026 01:48:05 -0400 Subject: [PATCH] netcode-revival foundation: fix cvar registry teardown SIOF + imgui RasterizerGamma - cvar.cpp: the static FlagRegistrar destructors run during __cxa_finalize and touch the registry after its function-local statics are destroyed (static destruction-order fiasco) - the codegen tool segfaults at exit. Leak the registry/mutex/index so teardown order cannot bite. - imgui_drawer.cpp: drop ImFontConfig::RasterizerGamma assignments (removed from imgui); keeps the build working with the modern imgui a fresh submodule checkout provides (the pinned imgui commit no longer exists). --- src/core/cvar.cpp | 17 +++++++++++------ src/ui/imgui_drawer.cpp | 5 +++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/core/cvar.cpp b/src/core/cvar.cpp index 9d304be..0dbacd7 100644 --- a/src/core/cvar.cpp +++ b/src/core/cvar.cpp @@ -34,19 +34,24 @@ std::mutex g_mutex; // Recursive: FlagRegistrar chain methods re-enter; change callbacks invoked // from SetFlagByName must not mutate the registry. std::recursive_mutex& GetRegistryMutex() { - static std::recursive_mutex m; - return m; + // Leaky (heap, never destroyed) so teardown order can't bite: static + // FlagRegistrar destructors run during __cxa_finalize and unregister their + // flags; if these function-local statics are destroyed first, that + // teardown crashes (static destruction-order fiasco, seen at exit of the + // codegen tool). Intentionally leaked - the process is ending. + static auto* m = new std::recursive_mutex(); + return *m; } // Flag registry - use functions to avoid static init order issues std::vector& GetRegistryStorage() { - static std::vector registry; - return registry; + static auto* registry = new std::vector(); + return *registry; } std::unordered_map& GetRegistryIndex() { - static std::unordered_map index; - return index; + static auto* index = new std::unordered_map(); + return *index; } std::vector>& GetCommandLineOverrides() { diff --git a/src/ui/imgui_drawer.cpp b/src/ui/imgui_drawer.cpp index 50a26d0..4f5fa5f 100644 --- a/src/ui/imgui_drawer.cpp +++ b/src/ui/imgui_drawer.cpp @@ -387,7 +387,8 @@ void ImGuiDrawer::SetupFonts() { // DirectWrite white-on-black edge // profiles (identity was measurably thinner/dimmer). The *_on_light_ // variants below keep gamma 1.0 - dark-on-light needs no correction. - config.RasterizerGamma = 0.62f; + // (RasterizerGamma was removed from imgui's ImFontConfig; the modern + // rasterizer handles coverage gamma internally, so the knob is gone.) config.FontLoaderFlags = ImGuiFreeTypeBuilderFlags_NoHinting; ui_font_ = io.Fonts->AddFontFromMemoryCompressedBase85TTF( GetInterRegularCompressedBase85(), 18.0f, &config); @@ -408,7 +409,7 @@ void ImGuiDrawer::SetupFonts() { config_on_light.RasterizerMultiply = 1.0f; // Dark-on-light matches the browser with NO coverage curve (harness fit: // identity beat every contrast/gamma variant once bake==draw size). - config_on_light.RasterizerGamma = 1.0f; + // config_on_light.RasterizerGamma = 1.0f; (removed from imgui) ui_font_on_light_ = io.Fonts->AddFontFromMemoryCompressedBase85TTF( GetInterRegularCompressedBase85(), 18.0f, &config_on_light); ui_font_semibold_on_light_ = io.Fonts->AddFontFromMemoryCompressedBase85TTF(