From 8fa4d5c43f09260da1f1a97514c3bf1dc82a3b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Mon, 7 Mar 2022 17:45:23 +0100 Subject: [PATCH] pipewire: module-zeroconf-discover: handle when AvahiWatch is freed while dispatching When a particular AvahiWatch is being dispatched, it cannot be freed because `watch_callback()` accesses it after the callback. Introduce a member (`dispatching`) to coordinate the deferred freeing in that case. The timeouts are not affected because the `AvahiTimeout` object is not accessed after the callback is called. --- src/modules/module-zeroconf-discover/avahi-poll.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/modules/module-zeroconf-discover/avahi-poll.c b/src/modules/module-zeroconf-discover/avahi-poll.c index c6550137f..e098646a7 100644 --- a/src/modules/module-zeroconf-discover/avahi-poll.c +++ b/src/modules/module-zeroconf-discover/avahi-poll.c @@ -37,6 +37,7 @@ struct AvahiWatch { AvahiWatchEvent events; AvahiWatchCallback callback; void *userdata; + unsigned int dispatching; }; struct AvahiTimeout { @@ -65,9 +66,14 @@ static void watch_callback(void *data, int fd, uint32_t mask) { AvahiWatch *w = data; + w->dispatching += 1; + w->events = from_pw_events(mask); w->callback(w, fd, w->events, w->userdata); w->events = 0; + + if (--w->dispatching == 0 && !w->source) + free(w); } static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event, @@ -103,9 +109,11 @@ static AvahiWatchEvent watch_get_events(AvahiWatch *w) static void watch_free(AvahiWatch *w) { - struct impl *impl = w->impl; - pw_loop_destroy_source(impl->loop, w->source); - free(w); + pw_loop_destroy_source(w->impl->loop, w->source); + w->source = NULL; + + if (!w->dispatching) + free(w); } static void timeout_callback(void *data, uint64_t expirations)