thread-mq: Make pa_thread_mq_done more robust

While investigating bug 89672 it was found that pa_thread_mq_done
was called recursively. Regardless of whether the recursion should
be stopped by other means, it seems to make sense to make
pa_thread_mq_done more robust so that it can be called twice
(and even recursively) without harm.

BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=89672
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
This commit is contained in:
David Henningsson 2015-03-23 14:39:52 +01:00
parent 85f5d93306
commit 498689926f

View file

@ -148,20 +148,34 @@ void pa_thread_mq_done(pa_thread_mq *q) {
* msgs, other stuff). Hence do so if we aren't currently
* dispatching anyway. */
if (!pa_asyncmsgq_dispatching(q->outq))
pa_asyncmsgq_flush(q->outq, true);
if (q->outq && !pa_asyncmsgq_dispatching(q->outq)) {
/* Flushing the asyncmsgq can cause arbitrarily callbacks to run,
potentially causing recursion into pa_thread_mq_done again. */
pa_asyncmsgq *z = q->outq;
pa_asyncmsgq_ref(z);
pa_asyncmsgq_flush(z, true);
pa_asyncmsgq_unref(z);
}
if (q->main_mainloop) {
if (q->read_main_event)
q->main_mainloop->io_free(q->read_main_event);
if (q->write_main_event)
q->main_mainloop->io_free(q->write_main_event);
q->read_main_event = q->write_main_event = NULL;
}
if (q->thread_mainloop) {
if (q->read_thread_event)
q->thread_mainloop->io_free(q->read_thread_event);
if (q->write_thread_event)
q->thread_mainloop->io_free(q->write_thread_event);
q->read_thread_event = q->write_thread_event = NULL;
}
if (q->inq)
pa_asyncmsgq_unref(q->inq);
if (q->outq)
pa_asyncmsgq_unref(q->outq);
q->inq = q->outq = NULL;