summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Foreman <derek.foreman@collabora.com>2023-11-10 14:21:48 -0600
committerDaniel Stone <daniels@collabora.com>2024-01-22 12:34:14 +0000
commitb42218f790033c496c48c7d5ba1f8421db794d0b (patch)
tree3cccd51396bc8bed4db77f2b9c271016b652efd1
parent2f17d480e848dc8cbd047fab9f322f326da54df9 (diff)
client: Allow setting names for queues
Allow setting a name for an event queue. The queue is used only for printing additional debug information. Debug output can now show the name of the event queue an event is dispatched from, or the event queue of a proxy when a request is made. Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
-rw-r--r--src/connection.c11
-rw-r--r--src/wayland-client-core.h10
-rw-r--r--src/wayland-client.c96
-rw-r--r--src/wayland-private.h3
-rw-r--r--src/wayland-server.c2
-rw-r--r--tests/queue-test.c112
6 files changed, 218 insertions, 16 deletions
diff --git a/src/connection.c b/src/connection.c
index a6ad410..b89166f 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -1283,7 +1283,8 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
void
wl_closure_print(struct wl_closure *closure, struct wl_object *target,
- int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg))
+ int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg),
+ const char *queue_name)
{
int i;
struct argument_details arg;
@@ -1302,8 +1303,12 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
clock_gettime(CLOCK_REALTIME, &tp);
time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
- fprintf(f, "[%7u.%03u] %s%s%s#%u.%s(",
- time / 1000, time % 1000,
+ fprintf(f, "[%7u.%03u] ", time / 1000, time % 1000);
+
+ if (queue_name)
+ fprintf(f, "{%s} ", queue_name);
+
+ fprintf(f, "%s%s%s#%u.%s(",
discarded ? "discarded " : "",
send ? " -> " : "",
target->interface->name, target->id,
diff --git a/src/wayland-client-core.h b/src/wayland-client-core.h
index af50f1e..20b2a3b 100644
--- a/src/wayland-client-core.h
+++ b/src/wayland-client-core.h
@@ -225,6 +225,12 @@ wl_proxy_get_display(struct wl_proxy *proxy);
void
wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue);
+struct wl_event_queue *
+wl_proxy_get_queue(const struct wl_proxy *proxy);
+
+const char *
+wl_event_queue_get_name(const struct wl_event_queue *queue);
+
struct wl_display *
wl_display_connect(const char *name);
@@ -272,6 +278,10 @@ wl_display_roundtrip(struct wl_display *display);
struct wl_event_queue *
wl_display_create_queue(struct wl_display *display);
+struct wl_event_queue *
+wl_display_create_queue_with_name(struct wl_display *display,
+ const char *name);
+
int
wl_display_prepare_read_queue(struct wl_display *display,
struct wl_event_queue *queue);
diff --git a/src/wayland-client.c b/src/wayland-client.c
index 489f0a8..94438e3 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -77,6 +77,7 @@ struct wl_event_queue {
struct wl_list event_list;
struct wl_list proxy_list; /**< struct wl_proxy::queue_link */
struct wl_display *display;
+ char *name;
};
struct wl_display {
@@ -220,11 +221,15 @@ display_protocol_error(struct wl_display *display, uint32_t code,
}
static void
-wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display)
+wl_event_queue_init(struct wl_event_queue *queue,
+ struct wl_display *display,
+ const char *name)
{
wl_list_init(&queue->event_list);
wl_list_init(&queue->proxy_list);
queue->display = display;
+ if (name)
+ queue->name = strdup(name);
}
static void
@@ -305,8 +310,15 @@ wl_event_queue_release(struct wl_event_queue *queue)
struct wl_proxy *proxy, *tmp;
if (queue != &queue->display->default_queue) {
- wl_log("warning: queue %p destroyed while proxies "
- "still attached:\n", queue);
+ if (queue->name) {
+ wl_log("warning: queue \"%s\" "
+ "%p destroyed while proxies "
+ "still attached:\n", queue->name, queue);
+ } else {
+ wl_log("warning: queue "
+ "%p destroyed while proxies "
+ "still attached:\n", queue);
+ }
}
wl_list_for_each_safe(proxy, tmp, &queue->proxy_list,
@@ -350,6 +362,7 @@ wl_event_queue_destroy(struct wl_event_queue *queue)
pthread_mutex_lock(&display->mutex);
wl_event_queue_release(queue);
+ free(queue->name);
free(queue);
pthread_mutex_unlock(&display->mutex);
}
@@ -371,7 +384,30 @@ wl_display_create_queue(struct wl_display *display)
if (queue == NULL)
return NULL;
- wl_event_queue_init(queue, display);
+ wl_event_queue_init(queue, display, NULL);
+
+ return queue;
+}
+
+/** Create a new event queue for this display and give it a name
+ *
+ * \param display The display context object
+ * \param name A human readable queue name
+ * \return A new event queue associated with this display or NULL on
+ * failure.
+ *
+ * \memberof wl_display
+ */
+WL_EXPORT struct wl_event_queue *
+wl_display_create_queue_with_name(struct wl_display *display, const char *name)
+{
+ struct wl_event_queue *queue;
+
+ queue = zalloc(sizeof *queue);
+ if (queue == NULL)
+ return NULL;
+
+ wl_event_queue_init(queue, display, name);
return queue;
}
@@ -885,8 +921,13 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
goto err_unlock;
}
- if (debug_client)
- wl_closure_print(closure, &proxy->object, true, false, NULL);
+ if (debug_client) {
+ struct wl_event_queue *queue;
+
+ queue = wl_proxy_get_queue(proxy);
+ wl_closure_print(closure, &proxy->object, true, false, NULL,
+ wl_event_queue_get_name(queue));
+ }
if (wl_closure_send(closure, proxy->display->connection)) {
wl_log("Error sending request: %s\n", strerror(errno));
@@ -1188,8 +1229,8 @@ wl_display_connect_to_fd(int fd)
display->fd = fd;
wl_map_init(&display->objects, WL_MAP_CLIENT_SIDE);
- wl_event_queue_init(&display->default_queue, display);
- wl_event_queue_init(&display->display_queue, display);
+ wl_event_queue_init(&display->default_queue, display, "Default Queue");
+ wl_event_queue_init(&display->display_queue, display, "Display Queue");
pthread_mutex_init(&display->mutex, NULL);
pthread_cond_init(&display->reader_cond, NULL);
display->reader_count = 0;
@@ -1321,7 +1362,9 @@ wl_display_disconnect(struct wl_display *display)
wl_map_for_each(&display->objects, free_zombies, NULL);
wl_map_release(&display->objects);
wl_event_queue_release(&display->default_queue);
+ free(display->default_queue.name);
wl_event_queue_release(&display->display_queue);
+ free(display->display_queue.name);
pthread_mutex_destroy(&display->mutex);
pthread_cond_destroy(&display->reader_cond);
close(display->fd);
@@ -1611,7 +1654,8 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
proxy_destroyed = !!(proxy->flags & WL_PROXY_FLAG_DESTROYED);
if (proxy_destroyed) {
if (debug_client)
- wl_closure_print(closure, &proxy->object, false, true, id_from_object);
+ wl_closure_print(closure, &proxy->object, false, true,
+ id_from_object, queue->name);
destroy_queued_closure(closure);
return;
}
@@ -1620,13 +1664,15 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
if (proxy->dispatcher) {
if (debug_client)
- wl_closure_print(closure, &proxy->object, false, false, id_from_object);
+ wl_closure_print(closure, &proxy->object, false, false,
+ id_from_object, queue->name);
wl_closure_dispatch(closure, proxy->dispatcher,
&proxy->object, opcode);
} else if (proxy->object.implementation) {
if (debug_client)
- wl_closure_print(closure, &proxy->object, false, false, id_from_object);
+ wl_closure_print(closure, &proxy->object, false, false,
+ id_from_object, queue->name);
wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT,
&proxy->object, opcode, proxy->user_data);
@@ -2399,6 +2445,34 @@ wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
pthread_mutex_unlock(&proxy->display->mutex);
}
+/** Get a proxy's event queue
+ *
+ * \param proxy The proxy to query
+ *
+ * Return the event queue
+ */
+WL_EXPORT struct wl_event_queue *
+wl_proxy_get_queue(const struct wl_proxy *proxy)
+{
+ return proxy->queue;
+
+}
+/** Get the name of an event queue
+ *
+ * \param queue The queue to query
+ *
+ * Return the human readable name for the event queue
+ *
+ * This may be NULL if no name has been set.
+ *
+ * \memberof wl_proxy
+ */
+WL_EXPORT const char *
+wl_event_queue_get_name(const struct wl_event_queue *queue)
+{
+ return queue->name;
+}
+
/** Create a proxy wrapper for making queue assignments thread-safe
*
* \param proxy The proxy object to be wrapped
diff --git a/src/wayland-private.h b/src/wayland-private.h
index 9274f1b..6b50658 100644
--- a/src/wayland-private.h
+++ b/src/wayland-private.h
@@ -213,7 +213,8 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection);
void
wl_closure_print(struct wl_closure *closure,
struct wl_object *target, int send, int discarded,
- uint32_t (*n_parse)(union wl_argument *arg));
+ uint32_t (*n_parse)(union wl_argument *arg),
+ const char *queue_name);
void
wl_closure_destroy(struct wl_closure *closure);
diff --git a/src/wayland-server.c b/src/wayland-server.c
index e784ef6..1534114 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -157,7 +157,7 @@ log_closure(struct wl_resource *resource,
struct wl_protocol_logger_message message;
if (debug_server)
- wl_closure_print(closure, object, send, false, NULL);
+ wl_closure_print(closure, object, send, false, NULL, NULL);
if (!wl_list_empty(&display->protocol_loggers)) {
message.resource = resource;
diff --git a/tests/queue-test.c b/tests/queue-test.c
index 6562139..cb61a85 100644
--- a/tests/queue-test.c
+++ b/tests/queue-test.c
@@ -472,6 +472,106 @@ client_test_queue_destroy_default_with_attached_proxies(void)
}
static void
+check_queue_name(struct wl_proxy *proxy, const char *name)
+{
+ struct wl_event_queue *queue;
+ const char *queue_name;
+
+ queue = wl_proxy_get_queue(proxy);
+ queue_name = wl_event_queue_get_name(queue);
+ if (!name)
+ assert(!queue_name);
+ else
+ assert(strcmp(queue_name, name) == 0);
+}
+
+static struct wl_callback *
+roundtrip_named_queue_nonblock(struct wl_display *display,
+ struct wl_event_queue *queue,
+ const char *name)
+{
+ struct wl_callback *callback;
+ struct wl_display *wrapped_display = NULL;
+
+ if (queue) {
+ wrapped_display = wl_proxy_create_wrapper(display);
+ assert(wrapped_display);
+ wl_proxy_set_queue((struct wl_proxy *) wrapped_display, queue);
+ check_queue_name((struct wl_proxy *) wrapped_display, name);
+
+ callback = wl_display_sync(wrapped_display);
+ } else
+ callback = wl_display_sync(display);
+
+ check_queue_name((struct wl_proxy *) callback, name);
+
+ if (wrapped_display)
+ wl_proxy_wrapper_destroy(wrapped_display);
+
+ assert(callback != NULL);
+
+ return callback;
+}
+
+static void
+client_test_queue_names(void)
+{
+ struct wl_event_queue *queue1, *queue2, *queue3;
+ struct wl_display *display;
+ struct wl_callback *callback1, *callback2, *callback3, *callback4;
+ struct wl_event_queue *default_queue;
+ char *log;
+ size_t log_len;
+ const char *default_queue_name;
+
+ display = wl_display_connect(NULL);
+ assert(display);
+
+ default_queue = wl_proxy_get_queue((struct wl_proxy *) display);
+ default_queue_name = wl_event_queue_get_name(default_queue);
+ assert(strcmp(default_queue_name, "Default Queue") == 0);
+
+ /* Create some event queues both with and without names. */
+ queue1 = wl_display_create_queue_with_name(display, "First");
+ assert(queue1);
+
+ queue2 = wl_display_create_queue_with_name(display, "Second");
+ assert(queue2);
+
+ queue3 = wl_display_create_queue(display);
+ assert(queue3);
+
+ /* Create some requests and ensure their queues have the expected
+ * names.
+ */
+ callback1 = roundtrip_named_queue_nonblock(display, queue1, "First");
+ callback2 = roundtrip_named_queue_nonblock(display, queue2, "Second");
+ callback3 = roundtrip_named_queue_nonblock(display, queue3, NULL);
+ callback4 = roundtrip_named_queue_nonblock(display, NULL, "Default Queue");
+
+ /* Destroy one queue with proxies still attached so we can verify
+ * that the queue name is in the log message. */
+ wl_event_queue_destroy(queue2);
+ log = map_file(client_log_fd, &log_len);
+ assert(strstr(log, "Second"));
+
+ /* There's no reason for the First queue name to be present. */
+ assert(!strstr(log, "First"));
+
+ munmap(log, log_len);
+
+ wl_callback_destroy(callback1);
+ wl_callback_destroy(callback2);
+ wl_callback_destroy(callback3);
+ wl_callback_destroy(callback4);
+
+ wl_event_queue_destroy(queue1);
+ wl_event_queue_destroy(queue3);
+
+ wl_display_disconnect(display);
+}
+
+static void
dummy_bind(struct wl_client *client,
void *data, uint32_t version, uint32_t id)
{
@@ -597,3 +697,15 @@ TEST(queue_destroy_default_with_attached_proxies)
display_destroy(d);
}
+
+TEST(queue_names)
+{
+ struct display *d = display_create();
+
+ test_set_timeout(2);
+
+ client_create_noarg(d, client_test_queue_names);
+ display_run(d);
+
+ display_destroy(d);
+}