[PATCH wayland 6/8] client: unref or destroy proxy when releasing queue

Marek Chalupa mchqwerty at gmail.com
Fri Dec 19 05:53:05 PST 2014


When we release event queue with queued events, we can leak
proxies in some cases.

Signed-off-by: Marek Chalupa <mchqwerty at gmail.com>
---
 src/wayland-client.c | 103 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 60 insertions(+), 43 deletions(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index 21799cd..f3b3452 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;
-- 
2.1.0



More information about the wayland-devel mailing list