summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2017-12-13 11:51:19 +0100
committerDaniel Stone <daniels@collabora.com>2018-02-09 17:00:04 +0000
commitbf7cc6805396af8df3b40e10c63de701346c93dd (patch)
treeaff21a2baebdb50b55fdeaa739d028e5e1d8754d
parentef48ff21f0468c428127d131b27cbddc627a83a6 (diff)
server: add wl_display_destroy_clients()
Bug [1] reported that wl_display_destroy() doesn't destroy clients, so client socket file descriptors are being kept open until the compositor process exits. Patch [2] proposed to destroy clients in wl_display_destroy(). The patch was not accepted because doing so changes the ABI. Thus, a new wl_display_destroy_clients() function is added in this patch. It should be called by compositors right before wl_display_destroy(). [1] https://bugs.freedesktop.org/show_bug.cgi?id=99142 [2] https://patchwork.freedesktop.org/patch/128832/ Signed-off-by: Simon Ser <contact@emersion.fr> Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Acked-by: Daniel Stone <daniels@collabora.com>
-rw-r--r--src/wayland-server-core.h3
-rw-r--r--src/wayland-server.c38
2 files changed, 41 insertions, 0 deletions
diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h
index fd458c5..2e725d9 100644
--- a/src/wayland-server-core.h
+++ b/src/wayland-server-core.h
@@ -214,6 +214,9 @@ wl_display_run(struct wl_display *display);
void
wl_display_flush_clients(struct wl_display *display);
+void
+wl_display_destroy_clients(struct wl_display *display);
+
struct wl_client;
typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data,
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 7225b4e..eb1e500 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -1279,6 +1279,44 @@ wl_display_flush_clients(struct wl_display *display)
}
}
+/** Destroy all clients connected to the display
+ *
+ * \param display The display object
+ *
+ * This function should be called right before wl_display_destroy() to ensure
+ * all client resources are closed properly. Destroying a client from within
+ * wl_display_destroy_clients() is safe, but creating one will leak resources
+ * and raise a warning.
+ *
+ * \memberof wl_display
+ */
+WL_EXPORT void
+wl_display_destroy_clients(struct wl_display *display)
+{
+ struct wl_list tmp_client_list, *pos;
+ struct wl_client *client;
+
+ /* Move the whole client list to a temporary head because some new clients
+ * might be added to the original head. */
+ wl_list_init(&tmp_client_list);
+ wl_list_insert_list(&tmp_client_list, &display->client_list);
+ wl_list_init(&display->client_list);
+
+ /* wl_list_for_each_safe isn't enough here: it fails if the next client is
+ * destroyed by the destroy handler of the current one. */
+ while (!wl_list_empty(&tmp_client_list)) {
+ pos = tmp_client_list.next;
+ client = wl_container_of(pos, client, link);
+
+ wl_client_destroy(client);
+ }
+
+ if (!wl_list_empty(&display->client_list)) {
+ wl_log("wl_display_destroy_clients: cannot destroy all clients because "
+ "new ones were created by destroy callbacks\n");
+ }
+}
+
static int
socket_data(int fd, uint32_t mask, void *data)
{