From: Seunghun Lee Date: Thu, 18 May 2023 05:21:28 +0000 (+0900) Subject: wayland-server: Add mutex for wl_client's resources X-Git-Tag: accepted/tizen/unified/20230706.152204~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b3d271dd243d12b9865d400fddfa6618a9aa2821;p=platform%2Fupstream%2Fwayland.git wayland-server: Add mutex for wl_client's resources This patch is to prevent threads from accessing wl_client's resources at the same time. Change-Id: I5da933efd426b8535ba1cb6144ad0f47fe2e4415 --- diff --git a/src/wayland-server.c b/src/wayland-server.c index 2ffcd8c..b082d3e 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "wayland-util.h" #include "wayland-private.h" @@ -87,6 +88,8 @@ struct wl_client { char proc_name[WL_CLIENT_NAME_MAX]; int error; struct wl_priv_signal resource_created_signal; + pthread_mutex_t connection_mutex; + pthread_mutex_t objects_mutex; }; struct wl_display { @@ -247,6 +250,7 @@ handle_array(struct wl_resource *resource, uint32_t opcode, log_closure(resource, closure, true); + pthread_mutex_lock(&resource->client->connection_mutex); if (send_func(closure, resource->client->connection)) { if (errno == EAGAIN) { wl_event_source_fd_update(resource->client->source, @@ -256,6 +260,7 @@ handle_array(struct wl_resource *resource, uint32_t opcode, resource->client->error = 1; } } + pthread_mutex_unlock(&resource->client->connection_mutex); wl_closure_destroy(closure); } @@ -379,16 +384,19 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) int len; int pid; + pthread_mutex_lock(&client->connection_mutex); + pthread_mutex_lock(&client->objects_mutex); + if (mask & WL_EVENT_HANGUP) { wl_log("Mask has hangup flag set, client_proc(%s) PID(%d) mask[%x]\n", client->proc_name, client->pid, mask); wl_client_destroy(client); - return 1; + goto end; } if (mask & WL_EVENT_ERROR) { destroy_client_with_error(client, "socket error"); - return 1; + goto end; } if (mask & WL_EVENT_WRITABLE) { @@ -399,7 +407,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) if (len < 0 && errno != EAGAIN) { destroy_client_with_error( client, "failed to flush client connection"); - return 1; + goto end; } else if (len >= 0) { wl_event_source_fd_update(client->source, WL_EVENT_READABLE); @@ -415,7 +423,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) if (len == 0 || (len < 0 && errno != EAGAIN)) { destroy_client_with_error( client, "failed to read client connection"); - return 1; + goto end; } } @@ -505,6 +513,10 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) "error in client communication"); } +end: + pthread_mutex_unlock(&client->objects_mutex); + pthread_mutex_unlock(&client->connection_mutex); + return 1; } @@ -522,7 +534,9 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) WL_EXPORT void wl_client_flush(struct wl_client *client) { + pthread_mutex_lock(&client->connection_mutex); int ret = wl_connection_flush(client->connection); + pthread_mutex_unlock(&client->connection_mutex); if (ret < 0 && errno != EAGAIN && errno != EPIPE) wl_log("client_proc(%s) flush failed: ret(%d) errno(%d)\n", @@ -643,6 +657,9 @@ wl_client_create(struct wl_display *display, int fd) wl_client_get_process_name(client); + pthread_mutex_init(&client->connection_mutex, NULL); + pthread_mutex_init(&client->objects_mutex, NULL); + wl_list_insert(display->client_list.prev, &client->link); wl_priv_signal_emit(&display->create_client_signal, client); @@ -798,13 +815,17 @@ wl_resource_post_no_memory(struct wl_resource *resource) static bool resource_is_deprecated(struct wl_resource *resource) { - struct wl_map *map = &resource->client->objects; + struct wl_client *client = resource->client; int id = resource->object.id; + pthread_mutex_lock(&client->objects_mutex); + /* wl_client_add_resource() marks deprecated resources with the flag. */ - if (wl_map_lookup_flags(map, id) & WL_MAP_ENTRY_LEGACY) + if (wl_map_lookup_flags(&client->objects, id) & WL_MAP_ENTRY_LEGACY) return true; + pthread_mutex_unlock(&client->objects_mutex); + return false; } @@ -835,6 +856,8 @@ wl_resource_destroy(struct wl_resource *resource) uint32_t id; uint32_t flags; + pthread_mutex_lock(&client->objects_mutex); + id = resource->object.id; flags = wl_map_lookup_flags(&client->objects, id); destroy_resource(resource, NULL, flags); @@ -848,6 +871,8 @@ wl_resource_destroy(struct wl_resource *resource) } else { wl_map_remove(&client->objects, id); } + + pthread_mutex_unlock(&client->objects_mutex); } WL_EXPORT uint32_t @@ -984,6 +1009,9 @@ wl_client_destroy(struct wl_client *client) wl_priv_signal_final_emit(&client->destroy_signal, client); + pthread_mutex_destroy(&client->objects_mutex); + pthread_mutex_destroy(&client->connection_mutex); + wl_client_flush(client); wl_map_for_each(&client->objects, destroy_resource, &serial); wl_map_release(&client->objects); @@ -1551,7 +1579,9 @@ wl_display_flush_clients(struct wl_display *display) int ret; wl_list_for_each_safe(client, next, &display->client_list, link) { + pthread_mutex_lock(&client->connection_mutex); ret = wl_connection_flush(client->connection); + pthread_mutex_unlock(&client->connection_mutex); if (ret < 0) wl_log("client_proc(%s) PID(%d) flush failed: ret(%d) errno(%d)\n", client->proc_name, client->pid, ret, errno); @@ -1963,14 +1993,19 @@ wl_resource_create(struct wl_client *client, { struct wl_resource *resource; + pthread_mutex_lock(&client->objects_mutex); + resource = zalloc(sizeof *resource); - if (resource == NULL) + if (resource == NULL) { + pthread_mutex_unlock(&client->objects_mutex); return NULL; + } if (id == 0) { id = wl_map_insert_new(&client->objects, 0, NULL); if (id == 0) { free(resource); + pthread_mutex_unlock(&client->objects_mutex); return NULL; } } @@ -1995,9 +2030,12 @@ wl_resource_create(struct wl_client *client, "invalid new id %d", id); } free(resource); + pthread_mutex_unlock(&client->objects_mutex); return NULL; } + pthread_mutex_unlock(&client->objects_mutex); + wl_priv_signal_emit(&client->resource_created_signal, resource); return resource; } @@ -2095,6 +2133,11 @@ wl_display_add_shm_format(struct wl_display *display, uint32_t format) return p; } +/* TIZEN_ONLY(20230704) : wayland-server: Add mutex for wl_client's resources + * + * WARNING: The `wl_map *` returned by this API is NOT thread-safe since the + * commit described above was introduced. + */ WL_EXPORT struct wl_map * wl_client_get_resources(struct wl_client *client) { @@ -2240,7 +2283,9 @@ wl_client_for_each_resource(struct wl_client *client, .it = iterator, }; + pthread_mutex_lock(&client->objects_mutex); wl_map_for_each(&client->objects, resource_iterator_helper, &context); + pthread_mutex_unlock(&client->objects_mutex); } static void