client: add mutex lock/unlock for proxy
authorBoram Park <boram1288.park@samsung.com>
Sun, 19 Feb 2017 11:57:10 +0000 (20:57 +0900)
committerJunkyeong Kim <jk0430.kim@samsung.com>
Thu, 16 Feb 2023 09:56:47 +0000 (18:56 +0900)
Actually this is not the perfect solution to protect wayland client resources in
multi-threads. They SHOULD be protected by applications. For example, during polling
the display fd, if a thread calls wl_display_disconnect, it will make issues. However,
adding mutex lock/unlock looks worth to protect wayland client resources inside of
wayland library at least.

Change-Id: I26b5f9598ccaaf5620a64a84af49f8637a360acb

src/wayland-client.c

index 38e7694..b6271ff 100644 (file)
@@ -345,7 +345,9 @@ wl_display_create_queue(struct wl_display *display)
        if (queue == NULL)
                return NULL;
 
+       pthread_mutex_lock(&display->mutex);
        wl_event_queue_init(queue, display);
+       pthread_mutex_unlock(&display->mutex);
 
        return queue;
 }
@@ -576,17 +578,23 @@ WL_EXPORT int
 wl_proxy_add_listener(struct wl_proxy *proxy,
                      void (**implementation)(void), void *data)
 {
+       struct wl_display *display = proxy->display;
+
        if (proxy->flags & WL_PROXY_FLAG_WRAPPER)
                wl_abort("Proxy %p is a wrapper\n", proxy);
 
+       pthread_mutex_lock(&display->mutex);
        if (proxy->object.implementation || proxy->dispatcher) {
                wl_log("proxy %p already has listener\n", proxy);
+               pthread_mutex_unlock(&display->mutex);
                return -1;
        }
 
        proxy->object.implementation = implementation;
        proxy->user_data = data;
 
+       pthread_mutex_unlock(&display->mutex);
+
        return 0;
 }
 
@@ -606,7 +614,14 @@ wl_proxy_add_listener(struct wl_proxy *proxy,
 WL_EXPORT const void *
 wl_proxy_get_listener(struct wl_proxy *proxy)
 {
-       return proxy->object.implementation;
+       struct wl_display *display = proxy->display;
+       const void *listener;
+
+       pthread_mutex_lock(&display->mutex);
+       listener = proxy->object.implementation;
+       pthread_mutex_unlock(&display->mutex);
+
+       return listener;
 }
 
 /** Set a proxy's listener (with dispatcher)
@@ -634,11 +649,16 @@ wl_proxy_add_dispatcher(struct wl_proxy *proxy,
                        wl_dispatcher_func_t dispatcher,
                        const void *implementation, void *data)
 {
+       struct wl_display *display = proxy->display;
+
        if (proxy->flags & WL_PROXY_FLAG_WRAPPER)
                wl_abort("Proxy %p is a wrapper\n", proxy);
 
+       pthread_mutex_lock(&display->mutex);
+
        if (proxy->object.implementation || proxy->dispatcher) {
                wl_log("proxy %p already has listener\n", proxy);
+               pthread_mutex_unlock(&display->mutex);
                return -1;
        }
 
@@ -646,6 +666,8 @@ wl_proxy_add_dispatcher(struct wl_proxy *proxy,
        proxy->dispatcher = dispatcher;
        proxy->user_data = data;
 
+       pthread_mutex_unlock(&display->mutex);
+
        return 0;
 }
 
@@ -1157,6 +1179,7 @@ wl_display_connect_to_fd(int fd)
        wl_event_queue_init(&display->default_queue, display);
        wl_event_queue_init(&display->display_queue, display);
        pthread_mutex_init(&display->mutex, NULL);
+       pthread_mutex_lock(&display->mutex);
        pthread_cond_init(&display->reader_cond, NULL);
        display->reader_count = 0;
 
@@ -1200,9 +1223,12 @@ wl_display_connect_to_fd(int fd)
        if (display->connection == NULL)
                goto err_connection;
 
+       pthread_mutex_unlock(&display->mutex);
+
        return display;
 
  err_connection:
+       pthread_mutex_unlock(&display->mutex);
        pthread_mutex_destroy(&display->mutex);
        pthread_cond_destroy(&display->reader_cond);
        wl_map_release(&display->objects);
@@ -1282,11 +1308,14 @@ wl_display_connect(const char *name)
 WL_EXPORT void
 wl_display_disconnect(struct wl_display *display)
 {
+       pthread_mutex_lock(&display->mutex);
+
        wl_connection_destroy(display->connection);
        wl_map_for_each(&display->objects, free_zombies, NULL);
        wl_map_release(&display->objects);
        wl_event_queue_release(&display->default_queue);
        wl_event_queue_release(&display->display_queue);
+       pthread_mutex_unlock(&display->mutex);
        pthread_mutex_destroy(&display->mutex);
        pthread_cond_destroy(&display->reader_cond);
        close(display->fd);
@@ -2172,7 +2201,11 @@ wl_display_flush(struct wl_display *display)
 WL_EXPORT void
 wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
 {
+       struct wl_display *display = proxy->display;
+
+       pthread_mutex_lock(&display->mutex);
        proxy->user_data = user_data;
+       pthread_mutex_unlock(&display->mutex);
 }
 
 /** Get the user data associated with a proxy
@@ -2185,7 +2218,14 @@ wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
 WL_EXPORT void *
 wl_proxy_get_user_data(struct wl_proxy *proxy)
 {
-       return proxy->user_data;
+       struct wl_display *display = proxy->display;
+       void *user_data;
+
+       pthread_mutex_lock(&display->mutex);
+       user_data = proxy->user_data;
+       pthread_mutex_unlock(&display->mutex);
+
+       return user_data;
 }
 
 /** Get the protocol object version of a proxy object
@@ -2207,7 +2247,14 @@ wl_proxy_get_user_data(struct wl_proxy *proxy)
 WL_EXPORT uint32_t
 wl_proxy_get_version(struct wl_proxy *proxy)
 {
-       return proxy->version;
+       struct wl_display *display = proxy->display;
+       uint32_t version;
+
+       pthread_mutex_lock(&display->mutex);
+       version = proxy->version;
+       pthread_mutex_unlock(&display->mutex);
+
+       return version;
 }
 
 /** Get the id of a proxy object
@@ -2220,7 +2267,14 @@ wl_proxy_get_version(struct wl_proxy *proxy)
 WL_EXPORT uint32_t
 wl_proxy_get_id(struct wl_proxy *proxy)
 {
-       return proxy->object.id;
+       struct wl_display *display = proxy->display;
+       uint32_t id;
+
+       pthread_mutex_lock(&display->mutex);
+       id = proxy->object.id;
+       pthread_mutex_unlock(&display->mutex);
+
+       return id;
 }
 
 /** Set the tag of a proxy object
@@ -2297,7 +2351,14 @@ wl_proxy_get_tag(struct wl_proxy *proxy)
 WL_EXPORT const char *
 wl_proxy_get_class(struct wl_proxy *proxy)
 {
-       return proxy->object.interface->name;
+       struct wl_display *display = proxy->display;
+       const char *name;
+
+       pthread_mutex_lock(&display->mutex);
+       name = proxy->object.interface->name;
+       pthread_mutex_unlock(&display->mutex);
+
+       return name;
 }
 
 /** Assign a proxy to an event queue
@@ -2331,16 +2392,16 @@ wl_proxy_get_class(struct wl_proxy *proxy)
 WL_EXPORT void
 wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
 {
-       pthread_mutex_lock(&proxy->display->mutex);
+       struct wl_display *display = proxy->display;
 
+       pthread_mutex_lock(&display->mutex);
        if (queue) {
                assert(proxy->display == queue->display);
                proxy->queue = queue;
        } else {
                proxy->queue = &proxy->display->default_queue;
        }
-
-       pthread_mutex_unlock(&proxy->display->mutex);
+       pthread_mutex_unlock(&display->mutex);
 }
 
 /** Create a proxy wrapper for making queue assignments thread-safe
@@ -2425,6 +2486,7 @@ WL_EXPORT void
 wl_proxy_wrapper_destroy(void *proxy_wrapper)
 {
        struct wl_proxy *wrapper = proxy_wrapper;
+       struct wl_display *display = wrapper->display;
 
        if (!(wrapper->flags & WL_PROXY_FLAG_WRAPPER))
                wl_abort("Tried to destroy non-wrapper proxy with "
@@ -2432,7 +2494,10 @@ wl_proxy_wrapper_destroy(void *proxy_wrapper)
 
        assert(wrapper->refcount == 1);
 
+       pthread_mutex_lock(&display->mutex);
+       wrapper->flags |= WL_PROXY_FLAG_DESTROYED;
        free(wrapper);
+       pthread_mutex_unlock(&display->mutex);
 }
 
 WL_EXPORT void