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>
This commit is contained in:
parent
73cb90763c
commit
5c70c03190
|
@ -217,15 +217,59 @@ wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display)
|
|||
queue->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);
|
||||
}
|
||||
|
||||
|
@ -1076,37 +1124,6 @@ queue_event(struct wl_display *display, int len)
|
|||
return size;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user