1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2From: Lloyd Pique <[email protected]> 3Date: Thu, 10 Mar 2022 14:56:02 -0800 4Subject: [PATCH 1/6] connection: Simplify wl_closure_print 5 6Client message observers 1/6 7 8Cleans up wl_closure_print(), and adds a client-private closure_log() 9intermediate function. 10 11This patch simplifies wl_closure_print() slightly by moving some client-only 12details to a new closure_log() intermediate function. This new function will 13also handle delivering messages to the new listener callback in a subsequent 14patch. 15 16closure_log() internally handles the check for logging being enabled, 17simplifying its callers, and returns early if logging is not enabled. This check 18becomes a bit more complex when there can be listeners. 19 20closure_log() also handles the work same transformation performed by 21id_from_object(), by making a copy of the args, and applying the transform to 22the copy before passing the arguments to wl_closure_print(). Doing it this way 23means the same arguments can also be passed to the eventual listeners. 24 25The boolean "discarded" argument for wl_closure_print() has been replaced by a 26"discarded_reason" string argument, allowing an arbitrary reason string to be 27passed in. For now only "discarded[]" is printed as an empty reason string is 28passed if the message was discarded, but that will also change. 29 30Signed-off-by: Lloyd Pique <[email protected]> 31 32diff --git a/COPYING b/COPYING 33index eb25a4e..843b844 100644 34--- a/COPYING 35+++ b/COPYING 36@@ -2,6 +2,7 @@ Copyright © 2008-2012 Kristian Høgsberg 37 Copyright © 2010-2012 Intel Corporation 38 Copyright © 2011 Benjamin Franzke 39 Copyright © 2012 Collabora, Ltd. 40+Copyright 2022 Google LLC 41 42 Permission is hereby granted, free of charge, to any person obtaining a 43 copy of this software and associated documentation files (the "Software"), 44diff --git a/src/connection.c b/src/connection.c 45index ceaeac1..110b614 100644 46--- a/src/connection.c 47+++ b/src/connection.c 48@@ -1264,7 +1264,7 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection) 49 50 void 51 wl_closure_print(struct wl_closure *closure, struct wl_object *target, 52- int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg)) 53+ bool send, const char *discarded_reason) 54 { 55 int i; 56 struct argument_details arg; 57@@ -1283,9 +1283,11 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, 58 clock_gettime(CLOCK_REALTIME, &tp); 59 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000); 60 61- fprintf(f, "[%7u.%03u] %s%s%s@%u.%s(", 62+ fprintf(f, "[%7u.%03u] %s%s%s%s%s@%u.%s(", 63 time / 1000, time % 1000, 64- discarded ? "discarded " : "", 65+ (discarded_reason != NULL) ? "discarded[" : "", 66+ (discarded_reason != NULL) ? discarded_reason : "", 67+ (discarded_reason != NULL) ? "] " : "", 68 send ? " -> " : "", 69 target->interface->name, target->id, 70 closure->message->name); 71@@ -1330,10 +1332,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, 72 fprintf(f, "nil"); 73 break; 74 case 'n': 75- if (n_parse) 76- nval = n_parse(&closure->args[i]); 77- else 78- nval = closure->args[i].n; 79+ nval = closure->args[i].n; 80 81 fprintf(f, "new id %s@", 82 (closure->message->types[i]) ? 83diff --git a/src/wayland-client.c b/src/wayland-client.c 84index 105f9be..ae47307 100644 85--- a/src/wayland-client.c 86+++ b/src/wayland-client.c 87@@ -115,6 +115,73 @@ struct wl_display { 88 89 static int debug_client = 0; 90 91+/** 92+ * This helper function adjusts the closure arguments before they are logged. 93+ * On the client, after the call to create_proxies(), NEW_ID arguments will 94+ * point to a wl_proxy accessible via arg.o instead of being an int32 95+ * accessible by arg.n, which is what wl_closure_print() attempts to print. 96+ * This helper transforms the argument back into an id, so wl_closure_print() 97+ * doesn't need to handle that as a special case. 98+ * 99+ * \param closure closure to adjust 100+ * \param send if this is closure is for a request 101+ * 102+ */ 103+static void 104+adjust_closure_args_for_logging(struct wl_closure *closure, bool send) 105+{ 106+ int i; 107+ struct argument_details arg; 108+ const struct wl_proxy *proxy; 109+ const char *signature = closure->message->signature; 110+ 111+ // No adjustment needed for a send. 112+ if (send) 113+ return; 114+ 115+ for (i = 0; i < closure->count; i++) { 116+ signature = get_next_argument(signature, &arg); 117+ 118+ switch (arg.type) { 119+ case 'n': 120+ proxy = (struct wl_proxy *)closure->args[i].o; 121+ closure->args[i].n = proxy ? proxy->object.id : 0; 122+ break; 123+ } 124+ } 125+} 126+ 127+/** 128+ * This function helps log closures from the client, assuming logging is 129+ * enabled. 130+ * 131+ * \param closure closure for the message 132+ * \param proxy proxy for the message 133+ * \param send true if this is closure is for a request 134+ * \param discarded true if this is message is being discarded 135+ * 136+ */ 137+static void 138+closure_log(struct wl_closure *closure, struct wl_proxy *proxy, bool send, 139+ bool discarded) 140+{ 141+ struct wl_closure adjusted_closure = { 0 }; 142+ 143+ if (!debug_client) 144+ return; 145+ 146+ // Note: The real closure has extra data (referenced by its args 147+ // immediately following the structure in memory, but we don't 148+ // need to duplicate that. 149+ memcpy(&adjusted_closure, closure, sizeof(struct wl_closure)); 150+ 151+ // Adjust the closure arguments. 152+ adjust_closure_args_for_logging(&adjusted_closure, send); 153+ 154+ wl_closure_print(&adjusted_closure, &proxy->object, send, 155+ discarded ? "" : NULL); 156+} 157+ 158 /** 159 * This helper function wakes up all threads that are 160 * waiting for display->reader_cond (i. e. when reading is done, 161@@ -885,8 +952,7 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode, 162 goto err_unlock; 163 } 164 165- if (debug_client) 166- wl_closure_print(closure, &proxy->object, true, false, NULL); 167+ closure_log(closure, proxy, true, false); 168 169 if (wl_closure_send(closure, proxy->display->connection)) { 170 wl_log("Error sending request: %s\n", strerror(errno)); 171@@ -1579,19 +1645,6 @@ queue_event(struct wl_display *display, int len) 172 return size; 173 } 174 175-static uint32_t 176-id_from_object(union wl_argument *arg) 177-{ 178- struct wl_proxy *proxy; 179- 180- if (arg->o) { 181- proxy = (struct wl_proxy *)arg->o; 182- return proxy->object.id; 183- } 184- 185- return 0; 186-} 187- 188 static void 189 dispatch_event(struct wl_display *display, struct wl_event_queue *queue) 190 { 191@@ -1610,8 +1663,7 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue) 192 proxy = closure->proxy; 193 proxy_destroyed = !!(proxy->flags & WL_PROXY_FLAG_DESTROYED); 194 if (proxy_destroyed) { 195- if (debug_client) 196- wl_closure_print(closure, &proxy->object, false, true, id_from_object); 197+ closure_log(closure, proxy, false, true); 198 destroy_queued_closure(closure); 199 return; 200 } 201@@ -1619,15 +1671,11 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue) 202 pthread_mutex_unlock(&display->mutex); 203 204 if (proxy->dispatcher) { 205- if (debug_client) 206- wl_closure_print(closure, &proxy->object, false, false, id_from_object); 207- 208+ closure_log(closure, proxy, false, false); 209 wl_closure_dispatch(closure, proxy->dispatcher, 210 &proxy->object, opcode); 211 } else if (proxy->object.implementation) { 212- if (debug_client) 213- wl_closure_print(closure, &proxy->object, false, false, id_from_object); 214- 215+ closure_log(closure, proxy, false, false); 216 wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT, 217 &proxy->object, opcode, proxy->user_data); 218 } 219diff --git a/src/wayland-private.h b/src/wayland-private.h 220index 9274f1b..66fc78f 100644 221--- a/src/wayland-private.h 222+++ b/src/wayland-private.h 223@@ -211,9 +211,8 @@ int 224 wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection); 225 226 void 227-wl_closure_print(struct wl_closure *closure, 228- struct wl_object *target, int send, int discarded, 229- uint32_t (*n_parse)(union wl_argument *arg)); 230+wl_closure_print(struct wl_closure *closure, struct wl_object *target, 231+ bool send, const char *discarded_reason); 232 233 void 234 wl_closure_destroy(struct wl_closure *closure); 235diff --git a/src/wayland-server.c b/src/wayland-server.c 236index d51acc6..be98f7d 100644 237--- a/src/wayland-server.c 238+++ b/src/wayland-server.c 239@@ -157,7 +157,7 @@ log_closure(struct wl_resource *resource, 240 struct wl_protocol_logger_message message; 241 242 if (debug_server) 243- wl_closure_print(closure, object, send, false, NULL); 244+ wl_closure_print(closure, object, send, NULL); 245 246 if (!wl_list_empty(&display->protocol_loggers)) { 247 message.resource = resource; 248