mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-31 22:25:25 -04:00
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
1 changed files with 60 additions and 43 deletions
|
|
@ -217,15 +217,59 @@ wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display)
|
||||||
queue->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
|
static void
|
||||||
wl_event_queue_release(struct wl_event_queue *queue)
|
wl_event_queue_release(struct wl_event_queue *queue)
|
||||||
{
|
{
|
||||||
struct wl_closure *closure;
|
struct wl_closure *closure;
|
||||||
|
struct wl_proxy *proxy;
|
||||||
|
|
||||||
while (!wl_list_empty(&queue->event_list)) {
|
while (!wl_list_empty(&queue->event_list)) {
|
||||||
closure = container_of(queue->event_list.next,
|
closure = container_of(queue->event_list.next,
|
||||||
struct wl_closure, link);
|
struct wl_closure, link);
|
||||||
wl_list_remove(&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);
|
wl_closure_destroy(closure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -355,19 +399,9 @@ wl_proxy_create_for_id(struct wl_proxy *factory,
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Destroy a proxy object
|
void
|
||||||
*
|
proxy_destroy(struct wl_proxy *proxy)
|
||||||
* \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);
|
|
||||||
|
|
||||||
if (proxy->flags & WL_PROXY_FLAG_ID_DELETED)
|
if (proxy->flags & WL_PROXY_FLAG_ID_DELETED)
|
||||||
wl_map_remove(&proxy->display->objects, proxy->object.id);
|
wl_map_remove(&proxy->display->objects, proxy->object.id);
|
||||||
else if (proxy->object.id < WL_SERVER_ID_START)
|
else if (proxy->object.id < WL_SERVER_ID_START)
|
||||||
|
|
@ -383,7 +417,21 @@ wl_proxy_destroy(struct wl_proxy *proxy)
|
||||||
proxy->refcount--;
|
proxy->refcount--;
|
||||||
if (!proxy->refcount)
|
if (!proxy->refcount)
|
||||||
free(proxy);
|
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);
|
pthread_mutex_unlock(&display->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1076,37 +1124,6 @@ queue_event(struct wl_display *display, int len)
|
||||||
return size;
|
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
|
static void
|
||||||
dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
|
dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue