From 3d85c04df08f8a05fb4e107276882a0618dd41f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Ondra=C4=8Dka?= Date: Thu, 2 Apr 2026 09:51:45 +0200 Subject: [PATCH 1/2] glamor: free the link log on shader link failure glamor_link_glsl_prog() retrieves the GL link log when program linking fails and prints it with ErrorF(), but did not free the allocated log. Direct leak of 51 byte(s) in 1 object(s) allocated from: #0 in malloc #1 in glamor_link_glsl_prog ../glamor/glamor_core.c:105 #2 in _glamor_create_linear_gradient_program ../glamor/glamor_gradient.c:541 #3 in glamor_init_gradient_shader ../glamor/glamor_gradient.c:577 #4 in glamor_init ../glamor/glamor.c:870 #5 in xwl_glamor_init ../hw/xwayland/xwayland-glamor.c:247 #6 in xwl_screen_init ../hw/xwayland/xwayland-screen.c:1121 ... --- glamor/glamor_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 8a601d086..6db0bb79f 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -103,9 +103,12 @@ glamor_link_glsl_prog(ScreenPtr screen, GLint prog, const char *format, ...) glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); info = malloc(size); + if (!info) + return FALSE; glGetProgramInfoLog(prog, size, NULL, info); ErrorF("Failed to link: %s\n", info); + free(info); return FALSE; } return TRUE; 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 2/2] 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