[PATCH wayland 9/9] client: Consume file descriptors destined for zombie proxies

Derek Foreman derekf at osg.samsung.com
Fri Apr 7 20:27:55 UTC 2017


We need to close file descriptors sent to zombie proxies to avoid leaking
them, and perhaps more importantly, to prevent them from being dispatched
in events on other objects (since they would previously be left in the
buffer and potentially fed to following events destined for live proxies)

Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
---
 src/connection.c      |  6 ++++++
 src/wayland-client.c  | 30 ++++++++++++++++++++++++++++--
 src/wayland-private.h |  3 +++
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/src/connection.c b/src/connection.c
index 84f5d79..2bfdd82 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -192,6 +192,12 @@ close_fds(struct wl_buffer *buffer, int max)
 	buffer->tail += size;
 }
 
+void
+wl_connection_close_fds_in(struct wl_connection *connection, int max)
+{
+	close_fds(&connection->fds_in, max);
+}
+
 int
 wl_connection_destroy(struct wl_connection *connection)
 {
diff --git a/src/wayland-client.c b/src/wayland-client.c
index 2cd713d..30f3b0a 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -1212,9 +1212,26 @@ increase_closure_args_refcount(struct wl_closure *closure)
 	}
 }
 
+static void
+message_consume_fds(struct wl_connection *connection, const char *signature)
+{
+	unsigned int count, i, fds = 0;
+	struct argument_details arg;
+
+	count = arg_count_for_signature(signature);
+	for (i = 0; i < count; i++) {
+		signature = get_next_argument(signature, &arg);
+		if (arg.type == 'h')
+			fds++;
+	}
+	if (fds)
+		wl_connection_close_fds_in(connection, fds);
+}
+
 static int
 queue_event(struct wl_display *display, int len)
 {
+	void *map_entry;
 	uint32_t p[2], id;
 	int opcode, size;
 	struct wl_proxy *proxy;
@@ -1229,12 +1246,21 @@ queue_event(struct wl_display *display, int len)
 	if (len < size)
 		return 0;
 
-	proxy = wl_map_lookup(&display->objects, id);
-	if (!proxy || wl_object_is_zombie(&display->objects, id)) {
+	map_entry = wl_map_lookup(&display->objects, id);
+	if (!map_entry) {
 		wl_connection_consume(display->connection, size);
 		return size;
 	}
 
+	if (wl_object_is_zombie(&display->objects, id)) {
+		struct wl_interface *interface = map_entry;
+
+		message_consume_fds(display->connection,
+				    interface->events[opcode].signature);
+		wl_connection_consume(display->connection, size);
+		return size;
+	}
+	proxy = map_entry;
 	message = &proxy->object.interface->events[opcode];
 	closure = wl_connection_demarshal(display->connection, size,
 					  &display->objects, message);
diff --git a/src/wayland-private.h b/src/wayland-private.h
index 2acd2d4..286ffe1 100644
--- a/src/wayland-private.h
+++ b/src/wayland-private.h
@@ -255,4 +255,7 @@ wl_priv_signal_get(struct wl_priv_signal *signal, wl_notify_func_t notify);
 void
 wl_priv_signal_emit(struct wl_priv_signal *signal, void *data);
 
+void
+wl_connection_close_fds_in(struct wl_connection *connection, int max);
+
 #endif
-- 
2.11.0



More information about the wayland-devel mailing list