summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2015-03-23 14:39:52 +0100
committerDavid Henningsson <david.henningsson@canonical.com>2015-03-27 14:34:12 +0100
commit498689926fc3a13207ec07128339972cdbb2eefc (patch)
treef4f1085e06ceca17c0f87b7b081e75d0c9e5c443
parent85f5d93306888bd3ee09497056bfa1b1e32bd51f (diff)
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>
-rw-r--r--src/pulsecore/thread-mq.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c
index d00641dce..f4489ac31 100644
--- a/src/pulsecore/thread-mq.c
+++ b/src/pulsecore/thread-mq.c
@@ -148,21 +148,35 @@ 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);
+ }
- q->main_mainloop->io_free(q->read_main_event);
- q->main_mainloop->io_free(q->write_main_event);
- q->read_main_event = q->write_main_event = NULL;
+ 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) {
- q->thread_mainloop->io_free(q->read_thread_event);
- q->thread_mainloop->io_free(q->write_thread_event);
+ 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;
}
- pa_asyncmsgq_unref(q->inq);
- pa_asyncmsgq_unref(q->outq);
+ if (q->inq)
+ pa_asyncmsgq_unref(q->inq);
+ if (q->outq)
+ pa_asyncmsgq_unref(q->outq);
q->inq = q->outq = NULL;
q->main_mainloop = NULL;