From 51064c1b4e46be180d4aa9b3fcfd57a6ea7ea615 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 19 Aug 2022 17:08:42 +0200 Subject: [PATCH 1/3] wayland: Ensure to unlink destroy listeners after destruction This is missed in some wl_listeners added through wl_resource_add_destroy_listener(). Ensure this is done consistently for all notify functions. Part-of: --- src/wayland/meta-wayland-data-device.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c index c8cf8f5c4b..d6c28ff331 100644 --- a/src/wayland/meta-wayland-data-device.c +++ b/src/wayland/meta-wayland-data-device.c @@ -173,11 +173,13 @@ unset_selection_source (MetaWaylandDataDevice *data_device, } static void -destroy_drag_focus (struct wl_listener *listener, void *data) +destroy_drag_focus (struct wl_listener *listener, + void *data) { MetaWaylandDragGrab *grab = wl_container_of (listener, grab, drag_focus_listener); grab->drag_focus_data_device = NULL; + wl_list_remove (&grab->drag_focus_listener.link); g_clear_signal_handler (&grab->drag_focus_destroy_handler_id, grab->drag_focus); @@ -560,12 +562,14 @@ drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was) } static void -destroy_data_device_icon (struct wl_listener *listener, void *data) +destroy_data_device_icon (struct wl_listener *listener, + void *data) { MetaWaylandDragGrab *drag_grab = wl_container_of (listener, drag_grab, drag_icon_listener); drag_grab->drag_surface = NULL; + wl_list_remove (&drag_grab->drag_icon_listener.link); if (drag_grab->feedback_actor) clutter_actor_remove_all_children (drag_grab->feedback_actor); -- GitLab From f4f39d3a2cd2de35e1f85e32182a34336d52ae3d Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 19 Aug 2022 17:10:15 +0200 Subject: [PATCH 2/3] wayland: Ensure to unlink destroy listeners for subsurfaces There is some surface tracking going on here, and all notify handlers are possibly leaving the linked wl_listener behind. Ensure it is unlinked in all destroy notification functions. Part-of: --- src/wayland/meta-wayland-subsurface.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c index 3e088b04fb..6a23c86100 100644 --- a/src/wayland/meta-wayland-subsurface.c +++ b/src/wayland/meta-wayland-subsurface.c @@ -342,6 +342,7 @@ subsurface_handle_pending_subsurface_destroyed (struct wl_listener *listener, wl_container_of (listener, op, subsurface_destroy_listener); op->surface = NULL; + wl_list_remove (&op->subsurface_destroy_listener.link); } static void @@ -352,6 +353,7 @@ subsurface_handle_pending_sibling_destroyed (struct wl_listener *listener, wl_container_of (listener, op, sibling_destroy_listener); op->sibling = NULL; + wl_list_remove (&op->sibling_destroy_listener.link); } void @@ -487,6 +489,7 @@ surface_handle_parent_surface_destroyed (struct wl_listener *listener, g_node_unlink (surface->subsurface_branch_node); surface->sub.parent = NULL; + wl_list_remove (&surface->sub.parent_destroy_listener.link); } static gboolean -- GitLab From 9c402bd091255e8a21f7e3263559dbe63135dec7 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 19 Aug 2022 17:13:01 +0200 Subject: [PATCH 3/3] wayland: Ensure to remove destroy listener for MetaWaylandBuffer Avoid the chance of invalid memory access by leaving the wl_listener behind when handling the destroy notification. Part-of: --- src/wayland/meta-wayland-buffer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c index 557952b6fe..7a22f824bc 100644 --- a/src/wayland/meta-wayland-buffer.c +++ b/src/wayland/meta-wayland-buffer.c @@ -83,12 +83,13 @@ G_DEFINE_TYPE (MetaWaylandBuffer, meta_wayland_buffer, G_TYPE_OBJECT); static void meta_wayland_buffer_destroy_handler (struct wl_listener *listener, - void *data) + void *data) { MetaWaylandBuffer *buffer = wl_container_of (listener, buffer, destroy_listener); buffer->resource = NULL; + wl_list_remove (&buffer->destroy_listener.link); g_signal_emit (buffer, signals[RESOURCE_DESTROYED], 0); g_object_unref (buffer); } -- GitLab