From 04918f3b0bb9121d550e6b397b3fd9258e95734d Mon Sep 17 00:00:00 2001 From: Erik Kurzinger Date: Tue, 18 May 2021 11:49:37 -0400 Subject: [PATCH] desktop-shell: don't run fade animation if compositor is inactive When a window is closed, Weston will, by default, run a fade out animation and defer destroying the underlying surface until it completes. However, if the compositor is sleeping, and therefore not rendering any frames, this animation will *never* complete. Therefore, if windows are repeatedly created and destroyed while in sleep mode, these surfaces will keep accumulating, and since the buffers attached to them may be backed by an fd, eventually the ulimit will be reached resulting in a potential crash or other errors. This can be demonstrated repeatedly launching and killing an X11 application with Xwayland running. while true; do xterm & pid=$!; sleep 0.5; kill $pid; done As soon as the compositor goes to sleep, one can observe a steadily growing list of dmabufs in the output of lsof. As a fix, desktop_surface_removed should check whether the compositor is active before kicking off the fade animation. If it is not, it should instead drop the extra reference taken in desktop_surface_committed and then destroy the surface immediately. Signed-off-by: Erik Kurzinger --- desktop-shell/shell.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index f126393a..0d0daa3f 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -2464,22 +2464,28 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface, weston_desktop_surface_unlink_view(shsurf->view); if (weston_surface_is_mapped(surface) && shsurf->shell->win_close_animation_type == ANIMATION_FADE) { + + if (shsurf->shell->compositor->state == WESTON_COMPOSITOR_ACTIVE) { pixman_region32_fini(&surface->pending.input); pixman_region32_init(&surface->pending.input); pixman_region32_fini(&surface->input); pixman_region32_init(&surface->input); weston_fade_run(shsurf->view, 1.0, 0.0, 300.0, fade_out_done, shsurf); - } else { - weston_view_destroy(shsurf->view); + return; + } else { + --surface->ref_count; + } + } - if (shsurf->output_destroy_listener.notify) { - wl_list_remove(&shsurf->output_destroy_listener.link); - shsurf->output_destroy_listener.notify = NULL; - } + weston_surface_destroy(surface); - free(shsurf); + if (shsurf->output_destroy_listener.notify) { + wl_list_remove(&shsurf->output_destroy_listener.link); + shsurf->output_destroy_listener.notify = NULL; } + + free(shsurf); } static void