From c82a52a47e5e01246680b5d257fff7bc42cb48bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 2 Jul 2013 15:39:03 -0400 Subject: [PATCH] wayland-server: Remove error event posting from wl_resource_create The wl_client_add/new_object() functions sends out an NO_MEMORY error if the allocation fails. This was convenient in a couple of places where that was all the error handling that was needed. Unfortunately that looks like out-of-memory isn't handled at the call site and set a bad precedent for not cleaning up properly or not handling at all. As we're introducing wl_resource_create() as a replacement for those two functions, let's remove the automatic error event posting and require the caller to do that if necessary. This commit also introduces a new helper, wl_client_post_no_memory() to make it possible to send NO_MEMORY events from bind where we don't have a wl_resource. --- src/wayland-server.c | 38 +++++++++++++++++++++++++++++++++----- src/wayland-server.h | 2 ++ src/wayland-shm.c | 29 +++++++++++++++++++++++++---- 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/wayland-server.c b/src/wayland-server.c index 33fdb205..4efc2704 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -404,6 +404,13 @@ wl_client_get_object(struct wl_client *client, uint32_t id) return wl_map_lookup(&client->objects, id); } +WL_EXPORT void +wl_client_post_no_memory(struct wl_client *client) +{ + wl_resource_post_error(client->display_resource, + WL_DISPLAY_ERROR_NO_MEMORY, "no memory"); +} + WL_EXPORT void wl_resource_post_no_memory(struct wl_resource *resource) { @@ -599,6 +606,11 @@ display_sync(struct wl_client *client, uint32_t serial; callback = wl_resource_create(client, &wl_callback_interface, 1, id); + if (callback == NULL) { + wl_client_post_no_memory(client); + return; + } + serial = wl_display_get_serial(client->display); wl_callback_send_done(callback, serial); wl_resource_destroy(callback); @@ -621,6 +633,11 @@ display_get_registry(struct wl_client *client, registry_resource = wl_resource_create(client, &wl_registry_interface, 1, id); + if (registry_resource == NULL) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(registry_resource, ®istry_interface, display, unbind_resource); @@ -655,6 +672,11 @@ bind_display(struct wl_client *client, client->display_resource = wl_resource_create(client, &wl_display_interface, 1, id); + if (client->display_resource == NULL) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(client->display_resource, &display_interface, display, destroy_client_display_resource); @@ -1007,10 +1029,8 @@ wl_resource_create(struct wl_client *client, struct wl_resource *resource; resource = malloc(sizeof *resource); - if (resource == NULL) { - wl_resource_post_no_memory(client->display_resource); + if (resource == NULL) return NULL; - } if (id == 0) id = wl_map_insert_new(&client->objects, 0, NULL); @@ -1087,7 +1107,11 @@ wl_client_add_object(struct wl_client *client, struct wl_resource *resource; resource = wl_resource_create(client, interface, -1, id); - wl_resource_set_implementation(resource, implementation, data, NULL); + if (resource == NULL) + wl_client_post_no_memory(client); + else + wl_resource_set_implementation(resource, + implementation, data, NULL); return resource; } @@ -1105,7 +1129,11 @@ wl_client_new_object(struct wl_client *client, struct wl_resource *resource; resource = wl_resource_create(client, interface, -1, 0); - wl_resource_set_implementation(resource, implementation, data, NULL); + if (resource == NULL) + wl_client_post_no_memory(client); + else + wl_resource_set_implementation(resource, + implementation, data, NULL); return resource; } diff --git a/src/wayland-server.h b/src/wayland-server.h index 43789839..0a798f45 100644 --- a/src/wayland-server.h +++ b/src/wayland-server.h @@ -128,6 +128,8 @@ struct wl_listener *wl_client_get_destroy_listener(struct wl_client *client, struct wl_resource * wl_client_get_object(struct wl_client *client, uint32_t id); +void +wl_client_post_no_memory(struct wl_client *client); struct wl_listener { struct wl_list link; diff --git a/src/wayland-shm.c b/src/wayland-shm.c index dc9731b8..0d3c95c2 100644 --- a/src/wayland-shm.c +++ b/src/wayland-shm.c @@ -115,7 +115,7 @@ shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource, buffer = malloc(sizeof *buffer); if (buffer == NULL) { - wl_resource_post_no_memory(resource); + wl_client_post_no_memory(client); return; } @@ -129,6 +129,13 @@ shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource, buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, id); + if (buffer->resource == NULL) { + wl_client_post_no_memory(client); + shm_pool_unref(pool); + free(buffer); + return; + } + wl_resource_set_implementation(buffer->resource, &shm_buffer_interface, buffer, destroy_buffer); @@ -182,7 +189,7 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource, pool = malloc(sizeof *pool); if (pool == NULL) { - wl_resource_post_no_memory(resource); + wl_client_post_no_memory(client); goto err_close; } @@ -207,8 +214,12 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource, pool->resource = wl_resource_create(client, &wl_shm_pool_interface, 1, id); - if (!pool->resource) - goto err_free; + if (!pool->resource) { + wl_client_post_no_memory(client); + munmap(pool->data, pool->size); + free(pool); + return; + } wl_resource_set_implementation(pool->resource, &shm_pool_interface, @@ -233,6 +244,11 @@ bind_shm(struct wl_client *client, struct wl_resource *resource; resource = wl_resource_create(client, &wl_shm_interface, 1, id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &shm_interface, data, NULL); wl_shm_send_format(resource, WL_SHM_FORMAT_ARGB8888); @@ -276,6 +292,11 @@ wl_shm_buffer_create(struct wl_client *client, buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, id); + if (buffer->resource == NULL) { + free(buffer); + return NULL; + } + wl_resource_set_implementation(buffer->resource, &shm_buffer_interface, buffer, destroy_buffer);