From 5c91bb8d28ee86df6e75de43117dc11a7f908853 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Thu, 12 Oct 2017 13:18:15 +0200 Subject: [PATCH] compositor: protocol logger This is better than running Weston with WAYLAND_DEBUG=server: - It is enabled on demand, no unnecessary flooding and no need to restart the compositor if debug was enabled. - It prints client pointers so that messages with different clients can be seen apart. Signed-off-by: Pekka Paalanen parse and print message arguments in protocol_log_fn Signed-off-by: Maniraj Devadoss Reviewed-by: Pekka Paalanen Reviewed-by: Daniel Stone --- compositor/main.c | 130 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-) diff --git a/compositor/main.c b/compositor/main.c index a8243154..22f3a275 100644 --- a/compositor/main.c +++ b/compositor/main.c @@ -120,6 +120,7 @@ struct wet_compositor { static FILE *weston_logfile = NULL; static struct weston_debug_scope *log_scope; +static struct weston_debug_scope *protocol_scope; static int cached_tm_mday = -1; @@ -225,6 +226,116 @@ vlog_continue(const char *fmt, va_list argp) return vfprintf(weston_logfile, fmt, argp); } +static const char * +get_next_argument(const char *signature, char* type) +{ + for(; *signature; ++signature) { + switch(*signature) { + case 'i': + case 'u': + case 'f': + case 's': + case 'o': + case 'n': + case 'a': + case 'h': + *type = *signature; + return signature + 1; + } + } + *type = '\0'; + return signature; +} + +static void +protocol_log_fn(void *user_data, + enum wl_protocol_logger_type direction, + const struct wl_protocol_logger_message *message) +{ + FILE *fp; + char *logstr; + size_t logsize; + char timestr[128]; + struct wl_resource *res = message->resource; + const char *signature = message->message->signature; + int i; + char type; + + if (!weston_debug_scope_is_enabled(protocol_scope)) + return; + + fp = open_memstream(&logstr, &logsize); + if (!fp) + return; + + weston_debug_scope_timestamp(protocol_scope, + timestr, sizeof timestr); + fprintf(fp, "%s ", timestr); + fprintf(fp, "client %p %s ", wl_resource_get_client(res), + direction == WL_PROTOCOL_LOGGER_REQUEST ? "rq" : "ev"); + fprintf(fp, "%s@%u.%s(", + wl_resource_get_class(res), + wl_resource_get_id(res), + message->message->name); + + for (i = 0; i < message->arguments_count; i++) { + signature = get_next_argument(signature, &type); + + if (i > 0) + fprintf(fp, ", "); + + switch (type) { + case 'u': + fprintf(fp, "%u", message->arguments[i].u); + break; + case 'i': + fprintf(fp, "%d", message->arguments[i].i); + break; + case 'f': + fprintf(fp, "%f", + wl_fixed_to_double(message->arguments[i].f)); + break; + case 's': + fprintf(fp, "\"%s\"", message->arguments[i].s); + break; + case 'o': + if (message->arguments[i].o) { + struct wl_resource* resource; + resource = (struct wl_resource*) message->arguments[i].o; + fprintf(fp, "%s@%u", + wl_resource_get_class(resource), + wl_resource_get_id(resource)); + } + else + fprintf(fp, "nil"); + break; + case 'n': + fprintf(fp, "new id %s@", + (message->message->types[i]) ? + message->message->types[i]->name : + "[unknown]"); + if (message->arguments[i].n != 0) + fprintf(fp, "%u", message->arguments[i].n); + else + fprintf(fp, "nil"); + break; + case 'a': + fprintf(fp, "array"); + break; + case 'h': + fprintf(fp, "fd %d", message->arguments[i].h); + break; + } + } + + fprintf(fp, ")\n"); + + if (fclose(fp) == 0) + weston_debug_scope_write(protocol_scope, logstr, logsize); + + free(logstr); +} + static struct wl_list child_process_list; static struct weston_compositor *segv_compositor; @@ -2417,6 +2528,7 @@ int main(int argc, char *argv[]) struct wet_compositor wet = { 0 }; int require_input; int32_t wait_for_debugger = 0; + struct wl_protocol_logger *protologger = NULL; const struct weston_option core_options[] = { { WESTON_OPTION_STRING, "backend", 'B', &backend }, @@ -2521,9 +2633,18 @@ int main(int argc, char *argv[]) log_scope = weston_compositor_add_debug_scope(wet.compositor, "log", "Weston and Wayland log\n", NULL, NULL); - - if (debug_protocol) + protocol_scope = + weston_compositor_add_debug_scope(wet.compositor, + "proto", + "Wayland protocol dump for all clients.\n", + NULL, NULL); + + if (debug_protocol) { + protologger = wl_display_add_protocol_logger(display, + protocol_log_fn, + NULL); weston_compositor_enable_debug_protocol(wet.compositor); + } if (weston_compositor_init_config(wet.compositor, config) < 0) goto out; @@ -2634,6 +2755,11 @@ out: /* free(NULL) is valid, and it won't be NULL if it's used */ free(wet.parsed_options); + if (protologger) + wl_protocol_logger_destroy(protologger); + + weston_debug_scope_destroy(protocol_scope); + protocol_scope = NULL; weston_debug_scope_destroy(log_scope); log_scope = NULL; weston_compositor_destroy(wet.compositor);