drm-lease-v1: fix error codepath

We were crashing in the error codepath [1] when
wlr_drm_create_lease() fails.

To fix this, delay the creation of the wlr_drm_lease_v1 until the
request is granted. Previously we were allocating that struct early
without populating the drm_lease field. However that means we ended
up with a half-constructed struct in the error codepath which is
annoying to handle.

[1]: https://github.com/swaywm/sway/issues/7204#issuecomment-1269797356
This commit is contained in:
Simon Ser 2022-10-07 18:15:24 +02:00 committed by Simon Zeni
parent 3be6658ee7
commit 5c382f6344
2 changed files with 16 additions and 22 deletions

View file

@ -71,8 +71,7 @@ struct wlr_drm_lease_request_v1 {
struct wlr_drm_lease_connector_v1 **connectors; struct wlr_drm_lease_connector_v1 **connectors;
size_t n_connectors; size_t n_connectors;
/** NULL until the lease is submitted */ struct wl_resource *lease_resource;
struct wlr_drm_lease_v1 *lease;
bool invalid; bool invalid;

View file

@ -154,12 +154,17 @@ static void lease_handle_destroy(struct wl_listener *listener, void *data) {
struct wlr_drm_lease_v1 *wlr_drm_lease_request_v1_grant( struct wlr_drm_lease_v1 *wlr_drm_lease_request_v1_grant(
struct wlr_drm_lease_request_v1 *request) { struct wlr_drm_lease_request_v1 *request) {
assert(request->lease); assert(!request->invalid);
wlr_log(WLR_DEBUG, "Attempting to grant request %p", request); wlr_log(WLR_DEBUG, "Attempting to grant request %p", request);
struct wlr_drm_lease_v1 *lease = request->lease; struct wlr_drm_lease_v1 *lease = calloc(1, sizeof(*lease));
assert(!request->invalid); if (!lease) {
wl_resource_post_no_memory(request->resource);
return NULL;
}
lease->device = request->device;
lease->resource = request->lease_resource;
/* Transform connectors list into wlr_output for leasing */ /* Transform connectors list into wlr_output for leasing */
struct wlr_output *outputs[request->n_connectors + 1]; struct wlr_output *outputs[request->n_connectors + 1];
@ -192,6 +197,9 @@ struct wlr_drm_lease_v1 *wlr_drm_lease_request_v1_grant(
lease->destroy.notify = lease_handle_destroy; lease->destroy.notify = lease_handle_destroy;
wl_signal_add(&lease->drm_lease->events.destroy, &lease->destroy); wl_signal_add(&lease->drm_lease->events.destroy, &lease->destroy);
wl_list_insert(&lease->device->leases, &lease->link);
wl_resource_set_user_data(lease->resource, lease);
wlr_log(WLR_DEBUG, "Granting request %p", request); wlr_log(WLR_DEBUG, "Granting request %p", request);
wp_drm_lease_v1_send_lease_fd(lease->resource, fd); wp_drm_lease_v1_send_lease_fd(lease->resource, fd);
@ -202,12 +210,12 @@ struct wlr_drm_lease_v1 *wlr_drm_lease_request_v1_grant(
void wlr_drm_lease_request_v1_reject( void wlr_drm_lease_request_v1_reject(
struct wlr_drm_lease_request_v1 *request) { struct wlr_drm_lease_request_v1 *request) {
assert(request && request->lease); assert(request);
wlr_log(WLR_DEBUG, "Rejecting request %p", request); wlr_log(WLR_DEBUG, "Rejecting request %p", request);
request->invalid = true; request->invalid = true;
wp_drm_lease_v1_send_finished(request->lease->resource); wp_drm_lease_v1_send_finished(request->lease_resource);
} }
void wlr_drm_lease_v1_revoke(struct wlr_drm_lease_v1 *lease) { void wlr_drm_lease_v1_revoke(struct wlr_drm_lease_v1 *lease) {
@ -337,20 +345,7 @@ static void drm_lease_request_v1_handle_submit(
} }
} }
struct wlr_drm_lease_v1 *lease = calloc(1, sizeof(struct wlr_drm_lease_v1)); request->lease_resource = lease_resource;
if (!lease) {
wlr_log(WLR_ERROR, "Failed to allocate wlr_drm_lease_v1");
wl_resource_post_no_memory(resource);
return;
}
lease->device = request->device;
wl_list_insert(&lease->device->leases, &lease->link);
lease->resource = lease_resource;
wl_resource_set_user_data(lease_resource, lease);
request->lease = lease;
/* TODO: reject the request if the user does not grant it */ /* TODO: reject the request if the user does not grant it */
wl_signal_emit_mutable(&request->device->manager->events.request, wl_signal_emit_mutable(&request->device->manager->events.request,