[client] app: free overlays after display server shutdown
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled

The render thread freed the overlays as soon as it exited, while the
main thread could still be dispatching display server input callbacks
that iterate them. Free the overlays in lg_shutdown instead, once the
render thread has been joined and the display server has shut down.

The overlays now outlive the renderer, so overlayFreeImage must not
call into it; renderer deinitialization has already destroyed all
textures along with the context.
This commit is contained in:
Amit Mendapara
2026-08-11 18:11:12 +05:30
committed by Geoffrey McRae
parent 75f7d614a7
commit 8187177c7f
3 changed files with 28 additions and 10 deletions

View File

@@ -1078,13 +1078,6 @@ static int renderThread(void * unused)
app_setState(APP_STATE_SHUTDOWN);
if (g_state.overlays)
{
app_freeOverlays();
ll_free(g_state.overlays);
g_state.overlays = NULL;
}
lgTimerDestroy(tickTimer);
lgTimerDestroy(fpsTimer);
@@ -3505,6 +3498,9 @@ static void lg_shutdown(void)
}
LG_LOCK_FREE(l_cursorRepaint.lock);
// An evdev batch may call input handlers; join before input teardown
evdev_stop();
if (g_state.transport.ops)
{
lgInput_dropTransport();
@@ -3540,6 +3536,7 @@ static void lg_shutdown(void)
if (g_state.ds)
g_state.ds->shutdown();
lgClipboard_free();
app_releaseAllKeybinds();
@@ -3548,6 +3545,16 @@ static void lg_shutdown(void)
if (g_state.ds && g_state.dsInitialized)
g_state.ds->free();
// Input callbacks have stopped; the evdev state and overlays can go
evdev_free();
if (g_state.overlays)
{
app_freeOverlays();
ll_free(g_state.overlays);
g_state.overlays = NULL;
}
renderQueue_setSourceFns(NULL, NULL, NULL);
renderQueue_free();
LG_LOCK_FREE(g_state.videoSourceLock);