From 7516a98167326350fb6e1906224bbff04fbf4c62 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 28 Mar 2020 20:56:27 +0100 Subject: [PATCH] Gracefully handle inert wl_output resources Closes: https://github.com/swaywm/wlroots/issues/2088 --- include/wlr/types/wlr_output.h | 5 +++++ types/wlr_gamma_control_v1.c | 7 +++++++ types/wlr_screencopy_v1.c | 12 +++++++++--- types/wlr_xdg_output_v1.c | 22 ++++++++++++++-------- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 9d6e85b3..3b7f7ee3 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -369,6 +369,11 @@ bool wlr_output_set_gamma(struct wlr_output *output, size_t size, const uint16_t *r, const uint16_t *g, const uint16_t *b); bool wlr_output_export_dmabuf(struct wlr_output *output, struct wlr_dmabuf_attributes *attribs); +/** + * Returns the wlr_output matching the provided wl_output resource. If the + * resource isn't a wl_output, it aborts. If the resource is inert (because the + * wlr_output has been destroyed), NULL is returned. + */ struct wlr_output *wlr_output_from_resource(struct wl_resource *resource); /** * Locks the output to only use rendering instead of direct scan-out. This is diff --git a/types/wlr_gamma_control_v1.c b/types/wlr_gamma_control_v1.c index 7eb5df5b..a75e45db 100644 --- a/types/wlr_gamma_control_v1.c +++ b/types/wlr_gamma_control_v1.c @@ -161,6 +161,13 @@ static void gamma_control_manager_get_gamma_control(struct wl_client *client, wl_resource_set_implementation(gamma_control->resource, &gamma_control_impl, gamma_control, gamma_control_handle_resource_destroy); + if (output == NULL) { + wl_resource_set_user_data(gamma_control->resource, NULL); + zwlr_gamma_control_v1_send_failed(gamma_control->resource); + free(gamma_control); + return; + } + wl_signal_add(&output->events.destroy, &gamma_control->output_destroy_listener); gamma_control->output_destroy_listener.notify = diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c index f0f8f8c9..85012d55 100644 --- a/types/wlr_screencopy_v1.c +++ b/types/wlr_screencopy_v1.c @@ -379,13 +379,19 @@ static void capture_output(struct wl_client *wl_client, wl_client_post_no_memory(wl_client); return; } + wl_resource_set_implementation(frame->resource, &frame_impl, frame, + frame_handle_resource_destroy); + + if (output == NULL) { + wl_resource_set_user_data(frame->resource, NULL); + zwlr_screencopy_frame_v1_send_failed(frame->resource); + free(frame); + return; + } frame->client = client; client->ref++; - wl_resource_set_implementation(frame->resource, &frame_impl, frame, - frame_handle_resource_destroy); - wl_list_insert(&client->manager->frames, &frame->link); wl_list_init(&frame->output_precommit.link); diff --git a/types/wlr_xdg_output_v1.c b/types/wlr_xdg_output_v1.c index 79778e6a..e81080ba 100644 --- a/types/wlr_xdg_output_v1.c +++ b/types/wlr_xdg_output_v1.c @@ -96,6 +96,20 @@ static void output_manager_handle_get_xdg_output(struct wl_client *client, struct wlr_output_layout *layout = manager->layout; struct wlr_output *output = wlr_output_from_resource(output_resource); + struct wl_resource *xdg_output_resource = wl_resource_create(client, + &zxdg_output_v1_interface, wl_resource_get_version(resource), id); + if (!xdg_output_resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(xdg_output_resource, &output_implementation, + NULL, output_handle_resource_destroy); + + if (output == NULL) { + wl_list_init(wl_resource_get_link(xdg_output_resource)); + return; + } + struct wlr_output_layout_output *layout_output = wlr_output_layout_get(layout, output); assert(layout_output); @@ -109,14 +123,6 @@ static void output_manager_handle_get_xdg_output(struct wl_client *client, } assert(xdg_output); - struct wl_resource *xdg_output_resource = wl_resource_create(client, - &zxdg_output_v1_interface, wl_resource_get_version(resource), id); - if (!xdg_output_resource) { - wl_client_post_no_memory(client); - return; - } - wl_resource_set_implementation(xdg_output_resource, &output_implementation, - NULL, output_handle_resource_destroy); wl_list_insert(&xdg_output->resources, wl_resource_get_link(xdg_output_resource));