From 1f3e9045adebe37ea51e5361245c2007802589c9 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 21 May 2021 16:38:30 +0300 Subject: [PATCH] clients/window: fix leaks on start-up failure Trying to run viewporter-test with ASan leak checking, weston-desktop-shell helper client reports many leaks, because the compositor quits before the client can start. Hence the wl_display_roundtrip() fails. Clean up by calling display_destroy() when wl_display_roundtrip() fails. It's late enough that all kinds of things may have been allocated, so a special local tear-down path is not feasible. To make that work, display_destroy() must handle many things that might be NULL which normally aren't. Also display_create() needs to initialize lists early enough so that cleaning them up works. Signed-off-by: Pekka Paalanen --- clients/window.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/clients/window.c b/clients/window.c index 49574b57..a0f4dc68 100644 --- a/clients/window.c +++ b/clients/window.c @@ -1375,7 +1375,8 @@ create_cursors(struct display *display) static void destroy_cursors(struct display *display) { - wl_cursor_theme_destroy(display->cursor_theme); + if (display->cursor_theme) + wl_cursor_theme_destroy(display->cursor_theme); free(display->cursors); } @@ -6245,6 +6246,12 @@ display_create(int *argc, char *argv[]) if (d == NULL) return NULL; + wl_list_init(&d->window_list); + wl_list_init(&d->deferred_list); + wl_list_init(&d->input_list); + wl_list_init(&d->output_list); + wl_list_init(&d->global_list); + d->display = wl_display_connect(NULL); if (d->display == NULL) { fprintf(stderr, "failed to connect to Wayland display: %s\n", @@ -6266,17 +6273,13 @@ display_create(int *argc, char *argv[]) display_watch_fd(d, d->display_fd, EPOLLIN | EPOLLERR | EPOLLHUP, &d->display_task); - wl_list_init(&d->deferred_list); - wl_list_init(&d->input_list); - wl_list_init(&d->output_list); - wl_list_init(&d->global_list); - d->registry = wl_display_get_registry(d->display); wl_registry_add_listener(d->registry, ®istry_listener, d); if (wl_display_roundtrip(d->display) < 0) { fprintf(stderr, "Failed to process Wayland connection: %s\n", strerror(errno)); + display_destroy(d); return NULL; } @@ -6290,8 +6293,6 @@ display_create(int *argc, char *argv[]) d->theme = theme_create(); - wl_list_init(&d->window_list); - init_dummy_surface(d); return d; @@ -6327,15 +6328,18 @@ display_destroy(struct display *display) if (!wl_list_empty(&display->deferred_list)) fprintf(stderr, "toytoolkit warning: deferred tasks exist.\n"); - cairo_surface_destroy(display->dummy_surface); - free(display->dummy_surface_data); + if (display->dummy_surface) + cairo_surface_destroy(display->dummy_surface); + if (display->dummy_surface_data) + free(display->dummy_surface_data); display_destroy_outputs(display); display_destroy_inputs(display); xkb_context_unref(display->xkb_context); - theme_destroy(display->theme); + if (display->theme) + theme_destroy(display->theme); destroy_cursors(display); #ifdef HAVE_CAIRO_EGL @@ -6355,7 +6359,8 @@ display_destroy(struct display *display) if (display->data_device_manager) wl_data_device_manager_destroy(display->data_device_manager); - wl_compositor_destroy(display->compositor); + if (display->compositor) + wl_compositor_destroy(display->compositor); wl_registry_destroy(display->registry); close(display->epoll_fd);