This fixes a case where pa__done() is called while
AVAHI_MESSAGE_PUBLISH_ALL is waiting for processing. The
pa_asyncmsgq_wait_for(AVAHI_MESSAGE_SHUTDOWN_COMPLETE) call will
process all pending messages, and processing AVAHI_MESSAGE_PUBLISH_ALL
causes publish_all_services(), and that in turn accesses u->services,
which has been already freed at this point. If we are shutting down,
we shouldn't react to any of the messages that the Avahi thread is
sending to the main thread.
BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=76184
pa_hook_slot *sink_new_slot, *source_new_slot, *sink_unlink_slot, *source_unlink_slot, *sink_changed_slot, *source_changed_slot;
pa_native_protocol *native;
pa_hook_slot *sink_new_slot, *source_new_slot, *sink_unlink_slot, *source_unlink_slot, *sink_changed_slot, *source_changed_slot;
pa_native_protocol *native;
};
/* Runs in PA mainloop context */
};
/* Runs in PA mainloop context */
static int avahi_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
struct userdata *u = (struct userdata *) data;
static int avahi_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
struct userdata *u = (struct userdata *) data;
+ pa_assert(u);
+
+ if (u->shutting_down)
+ return 0;
+
switch (code) {
case AVAHI_MESSAGE_PUBLISH_ALL:
publish_all_services(u);
switch (code) {
case AVAHI_MESSAGE_PUBLISH_ALL:
publish_all_services(u);
pa_module_unload(u->core, u->module, true);
break;
pa_module_unload(u->core, u->module, true);
break;
- case AVAHI_MESSAGE_SHUTDOWN_COMPLETE:
- /* pa__done() is waiting for this */
- break;
-
default:
pa_assert_not_reached();
}
default:
pa_assert_not_reached();
}
if (u->avahi_poll)
pa_avahi_poll_free(u->avahi_poll);
if (u->avahi_poll)
pa_avahi_poll_free(u->avahi_poll);
- pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->msg), AVAHI_MESSAGE_SHUTDOWN_COMPLETE, NULL, 0, NULL, NULL);
+ pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->msg), AVAHI_MESSAGE_SHUTDOWN_COMPLETE, u, 0, NULL, NULL);
}
void pa__done(pa_module*m) {
}
void pa__done(pa_module*m) {
if (!(u = m->userdata))
return;
if (!(u = m->userdata))
return;
+ u->shutting_down = true;
+
pa_threaded_mainloop_lock(u->mainloop);
pa_mainloop_api_once(u->api, client_free, u);
pa_threaded_mainloop_unlock(u->mainloop);
pa_threaded_mainloop_lock(u->mainloop);
pa_mainloop_api_once(u->api, client_free, u);
pa_threaded_mainloop_unlock(u->mainloop);