[PATCH weston v4] libweston-desktop: fix stale ping when a wl_shell_surface is destroyed

Giulio Camuffo giuliocamuffo at gmail.com
Thu Dec 8 15:20:01 UTC 2016


When sending a ping event to a surface using the wl_shell interface,
if that surface is destroyed before we receive the pong we will never
receive it, even if the client is actually responsive, since the
interface does not exist anymore. So when the surface if destroyed
pretend it's a pong and reset the ping state.

Signed-off-by: Giulio Camuffo <giuliocamuffo at gmail.com>
---

v3: store the ping serial in the surface instead of the client wrapper
v4: removed leftover change

 libweston-desktop/wl-shell.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/libweston-desktop/wl-shell.c b/libweston-desktop/wl-shell.c
index 399139c..f75b022 100644
--- a/libweston-desktop/wl-shell.c
+++ b/libweston-desktop/wl-shell.c
@@ -57,6 +57,7 @@ struct weston_desktop_wl_shell_surface {
 	struct weston_desktop_seat *popup_seat;
 	enum weston_desktop_wl_shell_surface_state state;
 	struct wl_listener wl_surface_resource_destroy_listener;
+	uint32_t ping_serial;
 };
 
 static void
@@ -112,6 +113,7 @@ weston_desktop_wl_shell_surface_ping(struct weston_desktop_surface *dsurface,
 {
 	struct weston_desktop_wl_shell_surface *surface = user_data;
 
+	surface->ping_serial = serial;
 	wl_shell_surface_send_ping(surface->resource, serial);
 }
 
@@ -181,11 +183,27 @@ weston_desktop_wl_shell_change_state(struct weston_desktop_wl_shell_surface *sur
 }
 
 static void
+pong_client(struct weston_desktop_wl_shell_surface *surface)
+{
+	struct weston_desktop_client *client =
+		weston_desktop_surface_get_client(surface->surface);
+
+	weston_desktop_client_pong(client, surface->ping_serial);
+	surface->ping_serial = 0;
+}
+
+static void
 weston_desktop_wl_shell_surface_destroy(struct weston_desktop_surface *dsurface,
 					void *user_data)
 {
 	struct weston_desktop_wl_shell_surface *surface = user_data;
 
+	/* If the surface being destroyed was the one that was pinged before
+	 * we need to fake a pong here, because it cannot answer the ping anymore,
+	 * even if the client is responsive. */
+	if (surface->ping_serial != 0)
+		pong_client(surface);
+
 	wl_list_remove(&surface->wl_surface_resource_destroy_listener.link);
 
 	weston_desktop_wl_shell_surface_maybe_ungrab(surface);
@@ -203,8 +221,10 @@ weston_desktop_wl_shell_surface_protocol_pong(struct wl_client *wl_client,
 					      uint32_t serial)
 {
 	struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+	struct weston_desktop_wl_shell_surface *wls =
+		weston_desktop_surface_get_implementation_data(surface);
 
-	weston_desktop_client_pong(weston_desktop_surface_get_client(surface), serial);
+	pong_client(wls);
 }
 
 static void
-- 
2.10.2



More information about the wayland-devel mailing list