[PATCH] server: no errors to a dead client

Pekka Paalanen ppaalanen at gmail.com
Sun Nov 27 23:59:21 PST 2011


Do not try to send errors to an already dead client, while in the
middle of cleanup.

This fixes a segmentation fault in the demo compositor, when a client is
killed. The future wl_shell_surface patches will introduce a dependency
between a wl_surface and a wl_shell_surface objects: it is an error to
destroy a wl_surface while the related wl_shell_surface object exists.
The demo code detects this and sends an error to the client.

The error is also triggered during the automatic cleanup of a
disappeared client, where it is common to destroy a wl_surface before
the wl_shell_surface due to the id ordering.

Signed-off-by: Pekka Paalanen <ppaalanen at gmail.com>
---
 src/wayland-server.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/src/wayland-server.c b/src/wayland-server.c
index 7c93e3f..9358eb4 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -143,6 +143,17 @@ wl_resource_post_error(struct wl_resource *resource,
 	va_end(ap);
 
 	client->error = 1;
+
+	/*
+	 * When a client aborts, its resources are destroyed in id order,
+	 * which means the display resource is destroyed first. If destruction
+	 * of any later resources results in a protocol error, we end up here
+	 * with a NULL display_resource. Do not try to send errors to an
+	 * already dead client.
+	 */
+	if (!client->display_resource)
+		return;
+
 	wl_resource_post_event(client->display_resource,
 			       WL_DISPLAY_ERROR, resource, code, buffer);
 }
@@ -579,6 +590,13 @@ struct wl_display_interface display_interface = {
 };
 
 static void
+destroy_client_display_resource(struct wl_resource *resource)
+{
+	resource->client->display_resource = NULL;
+	free(resource);
+}
+
+static void
 bind_display(struct wl_client *client,
 	     void *data, uint32_t version, uint32_t id)
 {
@@ -588,6 +606,7 @@ bind_display(struct wl_client *client,
 	client->display_resource =
 		wl_client_add_object(client, &wl_display_interface,
 				     &display_interface, id, display);
+	client->display_resource->destroy = destroy_client_display_resource;
 
 	wl_list_for_each(global, &display->global_list, link)
 		wl_resource_post_event(client->display_resource,
-- 
1.7.3.4



More information about the wayland-devel mailing list