#include <sys/eventfd.h>
#include <sys/file.h>
#include <sys/stat.h>
+#include <pthread.h>
#include "wayland-util.h"
#include "wayland-private.h"
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 {
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,
resource->client->error = 1;
}
}
+ pthread_mutex_unlock(&resource->client->connection_mutex);
wl_closure_destroy(closure);
}
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) {
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);
if (len == 0 || (len < 0 && errno != EAGAIN)) {
destroy_client_with_error(
client, "failed to read client connection");
- return 1;
+ goto end;
}
}
"error in client communication");
}
+end:
+ pthread_mutex_unlock(&client->objects_mutex);
+ pthread_mutex_unlock(&client->connection_mutex);
+
return 1;
}
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",
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);
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;
}
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);
} else {
wl_map_remove(&client->objects, id);
}
+
+ pthread_mutex_unlock(&client->objects_mutex);
}
WL_EXPORT uint32_t
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);
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);
{
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;
}
}
"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;
}
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)
{
.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