From b01a85dfd5e8cda7170b7ba6fe66fc3800f93990 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Tue, 28 Feb 2023 23:42:59 +0200 Subject: [PATCH] client: Do not warn about attached proxies on default queue destruction. If the default queue is being destroyed, the client is disconnecting from the wl_display, so there is no possibility of subsequent events being queued to the destroyed default queue, which is what this warning is about. Note that interacting with (e.g., destroying) a wl_proxy after its wl_display is destroyed is a certain memory error, and this warning will indirectly warn about this issue. However, this memory error should be detected and warned about through a more deliberate mechanism. Signed-off-by: Alexandros Frantzis --- src/wayland-client.c | 14 ++++++---- tests/queue-test.c | 63 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/wayland-client.c b/src/wayland-client.c index a50fc18..054c0c7 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -304,14 +304,18 @@ wl_event_queue_release(struct wl_event_queue *queue) if (!wl_list_empty(&queue->proxy_list)) { struct wl_proxy *proxy, *tmp; - wl_log("warning: queue %p destroyed while proxies still " - "attached:\n", queue); + if (queue != &queue->display->default_queue) { + wl_log("warning: queue %p destroyed while proxies " + "still attached:\n", queue); + } wl_list_for_each_safe(proxy, tmp, &queue->proxy_list, queue_link) { - wl_log(" %s@%u still attached\n", - proxy->object.interface->name, - proxy->object.id); + if (queue != &queue->display->default_queue) { + wl_log(" %s@%u still attached\n", + proxy->object.interface->name, + proxy->object.id); + } proxy->queue = NULL; wl_list_remove(&proxy->queue_link); wl_list_init(&proxy->queue_link); diff --git a/tests/queue-test.c b/tests/queue-test.c index 63abc19..4129310 100644 --- a/tests/queue-test.c +++ b/tests/queue-test.c @@ -308,12 +308,22 @@ client_test_queue_set_queue_race(void) } static char * -map_file(int fd, size_t *len) +maybe_map_file(int fd, size_t *len) { char *data; *len = lseek(fd, 0, SEEK_END); data = mmap(0, *len, PROT_READ, MAP_PRIVATE, fd, 0); + + return data; +} + +static char * +map_file(int fd, size_t *len) +{ + char *data; + + data = maybe_map_file(fd, len); assert(data != MAP_FAILED && "Failed to mmap file"); return data; @@ -422,6 +432,45 @@ client_test_queue_proxy_event_to_destroyed_queue(void) wl_display_disconnect(display); } +static void +client_test_queue_destroy_default_with_attached_proxies(void) +{ + struct wl_display *display; + struct wl_callback *callback; + char *log; + size_t log_len; + char callback_name[24]; + int ret; + + display = wl_display_connect(NULL); + assert(display); + + /* Create a sync dispatching events on the default queue. */ + callback = wl_display_sync(display); + assert(callback != NULL); + + /* Destroy the default queue (by disconnecting) before the attached + * object. */ + wl_display_disconnect(display); + + /* Check that the log does not contain any warning about the attached + * wl_callback proxy. */ + log = maybe_map_file(client_log_fd, &log_len); + ret = snprintf(callback_name, sizeof(callback_name), "wl_callback@%u", + wl_proxy_get_id((struct wl_proxy *) callback)); + assert(ret > 0 && ret < (int)sizeof(callback_name) && + "callback name creation failed (possibly truncated)"); + assert(log == MAP_FAILED || strstr(log, callback_name) == NULL); + if (log != MAP_FAILED) + munmap(log, log_len); + + /* HACK: Directly free the memory of the wl_callback proxy to appease + * ASan. We would normally use wl_callback_destroy(), but since we have + * destroyed the associated wl_display, using this function would lead + * to memory errors. */ + free(callback); +} + static void dummy_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) @@ -536,3 +585,15 @@ TEST(queue_proxy_event_to_destroyed_queue) /* Check that the client aborted. */ display_destroy_expect_signal(d, SIGABRT); } + +TEST(queue_destroy_default_with_attached_proxies) +{ + struct display *d = display_create(); + + test_set_timeout(2); + + client_create_noarg(d, client_test_queue_destroy_default_with_attached_proxies); + display_run(d); + + display_destroy(d); +}