From: Markus Ongyerth <[email protected]>

Add environment variable WAYLAND_DEBUG_INTERFACES for filtering the
output of WAYLAND_DEBUG logs.
While WAYLAND_DEBUG is a pretty powerful and useful debug tool, printing
everything has a few downsides.

1) It's a full keylogger (getting debug-logs from users)
2) It can be overly spammy with wl_buffer/wl_surface actions (e.g. when
   playing a video))

With this addition it's possible to supply another environment
variable, to filter on the interfaces one is interested in.
E.g. when interested in the behaviour of xdg-shell popups the filter could be
WAYLAND_DEBUG_INTERFACES=xdg_positioner,xdg_surface,xdg_popup
greatly improving SNR on the output and hiding potentially sensitive
information such as keystrokes.
---
 src/wayland-client.c | 85 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 81 insertions(+), 4 deletions(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index efeb745..9de8e4e 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -118,6 +118,31 @@ struct wl_display {
 /** \endcond */
 
 static int debug_client = 0;
+static size_t debug_client_count = 0;
+static char **debug_client_interfaces = NULL;
+
+static void
+wl_client_debug_print(struct wl_closure *closure,
+                      struct wl_object *target, int send)
+{
+       if (debug_client_interfaces) {
+               bool found = false;
+               size_t i;
+               for (i = 0; i < debug_client_count; ++i) {
+                       if (!strcmp(target->interface->name,
+                                   debug_client_interfaces[i])) {
+                               found = true;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       return;
+               }
+       }
+
+       wl_closure_print(closure, target, send);
+}
 
 /**
  * This helper function wakes up all threads that are
@@ -748,7 +773,7 @@ wl_proxy_marshal_array_constructor_versioned(struct 
wl_proxy *proxy,
                wl_abort("Error marshalling request: %s\n", strerror(errno));
 
        if (debug_client)
-               wl_closure_print(closure, &proxy->object, true);
+               wl_client_debug_print(closure, &proxy->object, true);
 
        if (wl_closure_send(closure, proxy->display->connection))
                wl_abort("Error sending request: %s\n", strerror(errno));
@@ -1016,6 +1041,56 @@ connect_to_socket(const char *name)
        return fd;
 }
 
+/* Set up the filter list for WAYLAND_DEBUG output.
+ * This reads WAYLAND_DEBUG_INTERFACEs and splits the provided string on every
+ * ','.
+ * The resulting list of strings is used as whitelist for interfaces printed by
+ * the WAYLAND_DEBUG mechanism.
+ * Sadly this leaks the memory required to strdup() the environment variable,
+ * but since this is a debug feature, and it should be constant over the
+ * lifetime of a single process, I consider it a minor problem
+ */
+static void
+setup_interface_filter(void)
+{
+       char *saveptr;
+       char *token;
+       size_t count = 0;
+       size_t i;
+       char *env;
+
+       /* We set this up before (on another wl_display_connect probably) so we
+        * don't have to do anything this time
+        */
+       if (debug_client_interfaces)
+               return;
+
+       if (!(env = getenv("WAYLAND_DEBUG_INTERFACES")))
+               return;
+
+       if (!(env = strdup(env))) {
+               wl_log("error: Could not allocate memory for 
WAYLAND_DEBUG_INTERFACES\n");
+               return;
+       }
+
+       for (i = 0; env[i]; ++i) {
+               if (env[i] == ',')
+                       ++count;
+       }
+
+       /* The maximum possible interfaces is the number of ',' found + 1 */
+       debug_client_interfaces = calloc(count + 1, sizeof(char *));
+       if (!debug_client_interfaces) {
+               wl_log("error: Could not allocate memory for 
WAYLAND_DEBUG_INTERFACES\n");
+               free(env);
+               return;
+       }
+
+       for (token = strtok_r(env, ",", &saveptr); token; token = 
strtok_r(NULL, ",", &saveptr)) {
+               debug_client_interfaces[debug_client_count++] = token;
+       }
+}
+
 /** Connect to Wayland display on an already open fd
  *
  * \param fd The fd to use for the connection
@@ -1034,8 +1109,10 @@ wl_display_connect_to_fd(int fd)
        const char *debug;
 
        debug = getenv("WAYLAND_DEBUG");
-       if (debug && (strstr(debug, "client") || strstr(debug, "1")))
+       if (debug && (strstr(debug, "client") || strstr(debug, "1"))) {
                debug_client = 1;
+               setup_interface_filter();
+       }
 
        display = zalloc(sizeof *display);
        if (display == NULL) {
@@ -1423,13 +1500,13 @@ dispatch_event(struct wl_display *display, struct 
wl_event_queue *queue)
 
        if (proxy->dispatcher) {
                if (debug_client)
-                       wl_closure_print(closure, &proxy->object, false);
+                       wl_client_debug_print(closure, &proxy->object, 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);
+                       wl_client_debug_print(closure, &proxy->object, false);
 
                wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT,
                                  &proxy->object, opcode, proxy->user_data);
-- 
2.18.0

_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to