From 83dc5453c6648b128f0cae1845cf5c06f499f1ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Ondra=C4=8Dka?= Date: Thu, 2 Apr 2026 10:15:28 +0200 Subject: [PATCH] xwayland: clean up glamor EGL state on fatal exits Xwayland initializes glamor on top of an EGL display, but some fatal exit paths bypass the normal screen close sequence. In particular, this can happen through xwl_give_up() after the Wayland compositor goes away, or through ddxGiveUp() after early startup failures such as keymap compilation failure. A relevant excerpt from the ASan report: Direct leak of 368 byte(s) in 1 object(s) allocated from: #0 in calloc #1 in dri2_display_create ../src/egl/drivers/dri2/egl_dri2.c:1014 #2 in dri2_initialize ../src/egl/drivers/dri2/egl_dri2.c:874 #3 in eglInitialize ../src/egl/main/eglapi.c:697 #4 in xwl_glamor_gbm_init_egl ../hw/xwayland/xwayland-glamor-gbm.c:1739 #5 in xwl_glamor_init ../hw/xwayland/xwayland-glamor.c:242 #6 in xwl_screen_init ../hw/xwayland/xwayland-screen.c:1121 #7 in AddScreen ../dix/dispatch.c:3999 #8 in InitOutput ../hw/xwayland/xwayland.c:437 #9 in dix_main ../dix/main.c:190 ... Direct leak of 32 byte(s) in 1 object(s) allocated from: #0 in calloc #1 in _eglCreateArray ../src/egl/main/eglarray.c:69 #2 in _eglLinkConfig ../src/egl/main/eglconfig.c:85 #3 in dri2_add_config ../src/egl/drivers/dri2/egl_dri2.c:457 #4 in drm_add_configs_for_visuals ../src/egl/drivers/dri2/platform_drm.c:563 #5 in dri2_initialize_drm ../src/egl/drivers/dri2/platform_drm.c:706 #6 in dri2_initialize ../src/egl/drivers/dri2/egl_dri2.c:892 #7 in eglInitialize ../src/egl/main/eglapi.c:697 ... --- hw/xwayland/xwayland-glamor-gbm.c | 17 ++++++++++++++++- hw/xwayland/xwayland-glamor-gbm.h | 1 + hw/xwayland/xwayland-glamor.c | 22 ++++++++++++++++++++++ hw/xwayland/xwayland-glamor.h | 1 + hw/xwayland/xwayland-screen.c | 18 +++++++++++++++--- hw/xwayland/xwayland.c | 3 +++ 6 files changed, 58 insertions(+), 4 deletions(-) diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c index f7f78560c..9518d49ab 100644 --- a/hw/xwayland/xwayland-glamor-gbm.c +++ b/hw/xwayland/xwayland-glamor-gbm.c @@ -1707,6 +1707,21 @@ xwl_glamor_gbm_init_main_dev(struct xwl_screen *xwl_screen) return TRUE; } +void +xwl_glamor_gbm_cleanup_egl(struct xwl_screen *xwl_screen) +{ + if (!xwl_screen->glamor) + return; + + if (xwl_screen->egl_display != EGL_NO_DISPLAY) { + xwl_glamor_maybe_destroy_context(xwl_screen); + eglTerminate(xwl_screen->egl_display); + xwl_screen->egl_display = EGL_NO_DISPLAY; + } + + xwl_glamor_gbm_cleanup(xwl_screen); +} + Bool xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen) { @@ -1845,7 +1860,7 @@ skip_drm_auth: return TRUE; error: - xwl_glamor_gbm_cleanup(xwl_screen); + xwl_glamor_gbm_cleanup_egl(xwl_screen); return FALSE; } diff --git a/hw/xwayland/xwayland-glamor-gbm.h b/hw/xwayland/xwayland-glamor-gbm.h index b346a0ba6..039deba77 100644 --- a/hw/xwayland/xwayland-glamor-gbm.h +++ b/hw/xwayland/xwayland-glamor-gbm.h @@ -40,6 +40,7 @@ Bool xwl_glamor_init_gbm(struct xwl_screen *xwl_screen); Bool xwl_glamor_has_wl_drm(struct xwl_screen *xwl_screen); Bool xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen); Bool xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen); +void xwl_glamor_gbm_cleanup_egl(struct xwl_screen *xwl_screen); drmDevice *xwl_gbm_get_main_device(struct xwl_screen *xwl_screen); /* Explicit buffer synchronization points */ diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c index b7f98d3ac..870f44599 100644 --- a/hw/xwayland/xwayland-glamor.c +++ b/hw/xwayland/xwayland-glamor.c @@ -50,6 +50,8 @@ #include +#include + static void glamor_egl_make_current(struct glamor_context *glamor_ctx) { @@ -268,3 +270,23 @@ xwl_glamor_init(struct xwl_screen *xwl_screen) return TRUE; } + +void +xwl_glamor_cleanup_all_screens(void) +{ + int i; + + for (i = 0; i < screenInfo.numScreens; i++) { + ScreenPtr screen = screenInfo.screens[i]; + struct xwl_screen *xwl_screen; + + if (!screen) + continue; + + xwl_screen = xwl_screen_get(screen); + if (!xwl_screen) + continue; + + xwl_glamor_gbm_cleanup_egl(xwl_screen); + } +} diff --git a/hw/xwayland/xwayland-glamor.h b/hw/xwayland/xwayland-glamor.h index ef312a857..0a20e590d 100644 --- a/hw/xwayland/xwayland-glamor.h +++ b/hw/xwayland/xwayland-glamor.h @@ -47,6 +47,7 @@ typedef enum _xwl_glamor_mode_flags{ #ifdef XWL_HAS_GLAMOR Bool xwl_glamor_init(struct xwl_screen *xwl_screen); +void xwl_glamor_cleanup_all_screens(void); Bool xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version); diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c index 0a21c449c..9fc752167 100644 --- a/hw/xwayland/xwayland-screen.c +++ b/hw/xwayland/xwayland-screen.c @@ -91,6 +91,10 @@ xwl_give_up(const char *f, ...) VErrorFSigSafe(f, args); va_end(args); +#ifdef XWL_HAS_GLAMOR + xwl_glamor_cleanup_all_screens(); +#endif + CloseWellKnownConnections(); OsCleanup(TRUE); fflush(stderr); @@ -237,9 +241,11 @@ Bool xwl_close_screen(ScreenPtr screen) { struct xwl_screen *xwl_screen = xwl_screen_get(screen); + CloseScreenProcPtr close_screen = xwl_screen->CloseScreen; struct xwl_output *xwl_output, *next_xwl_output; struct xwl_seat *xwl_seat, *next_xwl_seat; struct xwl_wl_surface *xwl_wl_surface, *xwl_wl_surface_next; + Bool ret; #ifdef XWL_HAS_GLAMOR xwl_dmabuf_feedback_destroy(&xwl_screen->default_feedback); #endif @@ -281,13 +287,18 @@ xwl_close_screen(ScreenPtr screen) RemoveNotifyFd(xwl_screen->wayland_fd); - wl_display_disconnect(xwl_screen->display); + screen->CloseScreen = close_screen; + ret = close_screen(screen); - screen->CloseScreen = xwl_screen->CloseScreen; +#ifdef XWL_HAS_GLAMOR + xwl_glamor_gbm_cleanup_egl(xwl_screen); +#endif + + wl_display_disconnect(xwl_screen->display); free(xwl_screen); - return screen->CloseScreen(screen); + return ret; } static struct xwl_seat * @@ -1180,6 +1191,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) #ifdef XWL_HAS_GLAMOR if (xwl_screen->glamor && !xwl_glamor_init(xwl_screen)) { ErrorF("Failed to initialize glamor, falling back to sw\n"); + xwl_glamor_gbm_cleanup_egl(xwl_screen); xwl_screen->glamor = XWL_GLAMOR_NONE; } #endif diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index d0be6028e..f8760cba0 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -61,6 +61,9 @@ extern _X_EXPORT Bool noXFree86VidModeExtension; void ddxGiveUp(enum ExitCode error) { +#ifdef XWL_HAS_GLAMOR + xwl_glamor_cleanup_all_screens(); +#endif } void