blob: 7223b1c434d2bc1273b7f32e35d2bbb9a48ae090 [file] [log] [blame]
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lloyd Pique <lpique@google.com>
Date: Thu, 10 Mar 2022 14:56:02 -0800
Subject: [PATCH 1/6] connection: Simplify wl_closure_print
Client message observers 1/6
Cleans up wl_closure_print(), and adds a client-private closure_log()
intermediate function.
This patch simplifies wl_closure_print() slightly by moving some client-only
details to a new closure_log() intermediate function. This new function will
also handle delivering messages to the new listener callback in a subsequent
patch.
closure_log() internally handles the check for logging being enabled,
simplifying its callers, and returns early if logging is not enabled. This check
becomes a bit more complex when there can be listeners.
closure_log() also handles the work same transformation performed by
id_from_object(), by making a copy of the args, and applying the transform to
the copy before passing the arguments to wl_closure_print(). Doing it this way
means the same arguments can also be passed to the eventual listeners.
The boolean "discarded" argument for wl_closure_print() has been replaced by a
"discarded_reason" string argument, allowing an arbitrary reason string to be
passed in. For now only "discarded[]" is printed as an empty reason string is
passed if the message was discarded, but that will also change.
Signed-off-by: Lloyd Pique <lpique@google.com>
diff --git a/COPYING b/COPYING
index eb25a4e..843b844 100644
--- a/COPYING
+++ b/COPYING
@@ -2,6 +2,7 @@ Copyright © 2008-2012 Kristian Høgsberg
Copyright © 2010-2012 Intel Corporation
Copyright © 2011 Benjamin Franzke
Copyright © 2012 Collabora, Ltd.
+Copyright 2022 Google LLC
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/src/connection.c b/src/connection.c
index ceaeac1..110b614 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -1264,7 +1264,7 @@ 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))
+ bool send, const char *discarded_reason)
{
int i;
struct argument_details arg;
@@ -1283,9 +1283,11 @@ 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(",
+ fprintf(f, "[%7u.%03u] %s%s%s%s%s@%u.%s(",
time / 1000, time % 1000,
- discarded ? "discarded " : "",
+ (discarded_reason != NULL) ? "discarded[" : "",
+ (discarded_reason != NULL) ? discarded_reason : "",
+ (discarded_reason != NULL) ? "] " : "",
send ? " -> " : "",
target->interface->name, target->id,
closure->message->name);
@@ -1330,10 +1332,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
fprintf(f, "nil");
break;
case 'n':
- if (n_parse)
- nval = n_parse(&closure->args[i]);
- else
- nval = closure->args[i].n;
+ nval = closure->args[i].n;
fprintf(f, "new id %s@",
(closure->message->types[i]) ?
diff --git a/src/wayland-client.c b/src/wayland-client.c
index 105f9be..ae47307 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -115,6 +115,73 @@ struct wl_display {
static int debug_client = 0;
+/**
+ * This helper function adjusts the closure arguments before they are logged.
+ * On the client, after the call to create_proxies(), NEW_ID arguments will
+ * point to a wl_proxy accessible via arg.o instead of being an int32
+ * accessible by arg.n, which is what wl_closure_print() attempts to print.
+ * This helper transforms the argument back into an id, so wl_closure_print()
+ * doesn't need to handle that as a special case.
+ *
+ * \param closure closure to adjust
+ * \param send if this is closure is for a request
+ *
+ */
+static void
+adjust_closure_args_for_logging(struct wl_closure *closure, bool send)
+{
+ int i;
+ struct argument_details arg;
+ const struct wl_proxy *proxy;
+ const char *signature = closure->message->signature;
+
+ // No adjustment needed for a send.
+ if (send)
+ return;
+
+ for (i = 0; i < closure->count; i++) {
+ signature = get_next_argument(signature, &arg);
+
+ switch (arg.type) {
+ case 'n':
+ proxy = (struct wl_proxy *)closure->args[i].o;
+ closure->args[i].n = proxy ? proxy->object.id : 0;
+ break;
+ }
+ }
+}
+
+/**
+ * This function helps log closures from the client, assuming logging is
+ * enabled.
+ *
+ * \param closure closure for the message
+ * \param proxy proxy for the message
+ * \param send true if this is closure is for a request
+ * \param discarded true if this is message is being discarded
+ *
+ */
+static void
+closure_log(struct wl_closure *closure, struct wl_proxy *proxy, bool send,
+ bool discarded)
+{
+ struct wl_closure adjusted_closure = { 0 };
+
+ if (!debug_client)
+ return;
+
+ // Note: The real closure has extra data (referenced by its args
+ // immediately following the structure in memory, but we don't
+ // need to duplicate that.
+ memcpy(&adjusted_closure, closure, sizeof(struct wl_closure));
+
+ // Adjust the closure arguments.
+ adjust_closure_args_for_logging(&adjusted_closure, send);
+
+ wl_closure_print(&adjusted_closure, &proxy->object, send,
+ discarded ? "" : NULL);
+}
+
/**
* This helper function wakes up all threads that are
* waiting for display->reader_cond (i. e. when reading is done,
@@ -885,8 +952,7 @@ 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);
+ closure_log(closure, proxy, true, false);
if (wl_closure_send(closure, proxy->display->connection)) {
wl_log("Error sending request: %s\n", strerror(errno));
@@ -1579,19 +1645,6 @@ queue_event(struct wl_display *display, int len)
return size;
}
-static uint32_t
-id_from_object(union wl_argument *arg)
-{
- struct wl_proxy *proxy;
-
- if (arg->o) {
- proxy = (struct wl_proxy *)arg->o;
- return proxy->object.id;
- }
-
- return 0;
-}
-
static void
dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
{
@@ -1610,8 +1663,7 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
proxy = closure->proxy;
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);
+ closure_log(closure, proxy, false, true);
destroy_queued_closure(closure);
return;
}
@@ -1619,15 +1671,11 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
pthread_mutex_unlock(&display->mutex);
if (proxy->dispatcher) {
- if (debug_client)
- wl_closure_print(closure, &proxy->object, false, false, id_from_object);
-
+ closure_log(closure, proxy, false, false);
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);
-
+ closure_log(closure, proxy, false, false);
wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT,
&proxy->object, opcode, proxy->user_data);
}
diff --git a/src/wayland-private.h b/src/wayland-private.h
index 9274f1b..66fc78f 100644
--- a/src/wayland-private.h
+++ b/src/wayland-private.h
@@ -211,9 +211,8 @@ int
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));
+wl_closure_print(struct wl_closure *closure, struct wl_object *target,
+ bool send, const char *discarded_reason);
void
wl_closure_destroy(struct wl_closure *closure);
diff --git a/src/wayland-server.c b/src/wayland-server.c
index d51acc6..be98f7d 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, NULL);
if (!wl_list_empty(&display->protocol_loggers)) {
message.resource = resource;