summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Chalupa <mchqwerty@gmail.com>2014-12-19 14:53:05 +0100
committerDaniel Stone <daniels@collabora.com>2015-01-28 17:17:19 +0000
commit5c70c031903352530f701ca4badf4be1763984a4 (patch)
treee1ecf74afdc4a6af343790bdfa06e07a2efa4a56
parent73cb90763ce17eab9b066c5916a367e243e538c9 (diff)
downloadwayland-5c70c031903352530f701ca4badf4be1763984a4.tar.gz
client: unref or destroy proxy when releasing queue
When we release event queue with queued events, we can leak proxies in some cases. Signed-off-by: Marek Chalupa <mchqwerty@gmail.com> Reviewed-by: Daniel Stone <daniels@collabora.com>
-rw-r--r--src/wayland-client.c103
1 files changed, 60 insertions, 43 deletions
diff --git a/src/wayland-client.c b/src/wayland-client.c
index 7a462aa..0f1405c 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -218,14 +218,58 @@ wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display)
}
static void
+decrease_closure_args_refcount(struct wl_closure *closure)
+{
+ const char *signature;
+ struct argument_details arg;
+ int i, count;
+ struct wl_proxy *proxy;
+
+ signature = closure->message->signature;
+ count = arg_count_for_signature(signature);
+ for (i = 0; i < count; i++) {
+ signature = get_next_argument(signature, &arg);
+ switch (arg.type) {
+ case 'n':
+ case 'o':
+ proxy = (struct wl_proxy *) closure->args[i].o;
+ if (proxy) {
+ if (proxy->flags & WL_PROXY_FLAG_DESTROYED)
+ closure->args[i].o = NULL;
+
+ proxy->refcount--;
+ if (!proxy->refcount)
+ free(proxy);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void
+proxy_destroy(struct wl_proxy *proxy);
+
+static void
wl_event_queue_release(struct wl_event_queue *queue)
{
struct wl_closure *closure;
+ struct wl_proxy *proxy;
while (!wl_list_empty(&queue->event_list)) {
closure = container_of(queue->event_list.next,
struct wl_closure, link);
wl_list_remove(&closure->link);
+
+ decrease_closure_args_refcount(closure);
+
+ proxy = closure->proxy;
+ if (proxy->refcount == 1)
+ proxy_destroy(proxy);
+ else
+ --proxy->refcount;
+
wl_closure_destroy(closure);
}
}
@@ -355,19 +399,9 @@ wl_proxy_create_for_id(struct wl_proxy *factory,
return proxy;
}
-/** Destroy a proxy object
- *
- * \param proxy The proxy to be destroyed
- *
- * \memberof wl_proxy
- */
-WL_EXPORT void
-wl_proxy_destroy(struct wl_proxy *proxy)
+void
+proxy_destroy(struct wl_proxy *proxy)
{
- struct wl_display *display = proxy->display;
-
- pthread_mutex_lock(&display->mutex);
-
if (proxy->flags & WL_PROXY_FLAG_ID_DELETED)
wl_map_remove(&proxy->display->objects, proxy->object.id);
else if (proxy->object.id < WL_SERVER_ID_START)
@@ -383,7 +417,21 @@ wl_proxy_destroy(struct wl_proxy *proxy)
proxy->refcount--;
if (!proxy->refcount)
free(proxy);
+}
+/** Destroy a proxy object
+ *
+ * \param proxy The proxy to be destroyed
+ *
+ * \memberof wl_proxy
+ */
+WL_EXPORT void
+wl_proxy_destroy(struct wl_proxy *proxy)
+{
+ struct wl_display *display = proxy->display;
+
+ pthread_mutex_lock(&display->mutex);
+ proxy_destroy(proxy);
pthread_mutex_unlock(&display->mutex);
}
@@ -1077,37 +1125,6 @@ queue_event(struct wl_display *display, int len)
}
static void
-decrease_closure_args_refcount(struct wl_closure *closure)
-{
- const char *signature;
- struct argument_details arg;
- int i, count;
- struct wl_proxy *proxy;
-
- signature = closure->message->signature;
- count = arg_count_for_signature(signature);
- for (i = 0; i < count; i++) {
- signature = get_next_argument(signature, &arg);
- switch (arg.type) {
- case 'n':
- case 'o':
- proxy = (struct wl_proxy *) closure->args[i].o;
- if (proxy) {
- if (proxy->flags & WL_PROXY_FLAG_DESTROYED)
- closure->args[i].o = NULL;
-
- proxy->refcount--;
- if (!proxy->refcount)
- free(proxy);
- }
- break;
- default:
- break;
- }
- }
-}
-
-static void
dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
{
struct wl_closure *closure;