[pulseaudio-commits] 4 commits - src/modules src/pulsecore

Tanu Kaskinen tanuk at kemper.freedesktop.org
Fri Mar 22 12:17:34 PDT 2013


 src/modules/module-filter-apply.c |   10 ++++--
 src/modules/module-loopback.c     |   55 ++++++++++++++++++++++++++------------
 src/pulsecore/conf-parser.c       |    3 --
 3 files changed, 45 insertions(+), 23 deletions(-)

New commits:
commit 6733caf114d0d759590459745c864aa9518d133d
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Sat Jun 30 12:58:40 2012 +0300

    conf-parser: Remove redundant feof() call
    
    fgets() returns NULL in case there's an error or f is at EOF. The
    while condition just checked that f is not at EOF, therefore an error
    must have happened.

diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c
index 062fa8e..0c7444d 100644
--- a/src/pulsecore/conf-parser.c
+++ b/src/pulsecore/conf-parser.c
@@ -185,9 +185,6 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, pa_p
 
     while (!feof(f)) {
         if (!fgets(state.buf, sizeof(state.buf), f)) {
-            if (feof(f))
-                break;
-
             pa_log_warn("Failed to read configuration file '%s': %s", filename, pa_cstrerror(errno));
             goto finish;
         }

commit 259be540e3bc7451305de09c196bc3b49dc38e53
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Thu Mar 14 22:07:14 2013 +0200

    loopback: Flush asyncmsgq from the right context
    
    u->asyncmsg is accessed from two IO threads. teardown() shouldn't
    flush the queue from the main thread while both IO threads are still
    potentially using the queue. This patch fixes that error by flushing
    the queue from the sink input thread when the sink input is being
    unlinked.
    
    Flushing the queue in teardown() caused this assertion in
    pa_asyncmsgq_get() to crash sometimes: pa_assert(!a->current)

diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index ea24c3b..6017891 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -138,29 +138,35 @@ static void teardown(struct userdata *u) {
     pa_assert(u);
     pa_assert_ctl_context();
 
-    if (u->asyncmsgq)
-        pa_asyncmsgq_flush(u->asyncmsgq, 0);
-
     u->adjust_time = 0;
     enable_adjust_timer(u, false);
 
-    if (u->sink_input)
-        pa_sink_input_unlink(u->sink_input);
+    /* Handling the asyncmsgq between the source output and the sink input
+     * requires some care. When the source output is unlinked, nothing needs
+     * to be done for the asyncmsgq, because the source output is the sending
+     * end. But when the sink input is unlinked, we should ensure that the
+     * asyncmsgq is emptied, because the messages in the queue hold references
+     * to the sink input. Also, we need to ensure that new messages won't be
+     * written to the queue after we have emptied it.
+     *
+     * Emptying the queue can be done in the state_changed() callback of the
+     * sink input, when the new state is "unlinked".
+     *
+     * Preventing new messages from being written to the queue can be achieved
+     * by unlinking the source output before unlinking the sink input. There
+     * are no other writers for that queue, so this is sufficient. */
 
-    if (u->source_output)
+    if (u->source_output) {
         pa_source_output_unlink(u->source_output);
+        pa_source_output_unref(u->source_output);
+        u->source_output = NULL;
+    }
 
     if (u->sink_input) {
-        u->sink_input->parent.process_msg = pa_sink_input_process_msg;
+        pa_sink_input_unlink(u->sink_input);
         pa_sink_input_unref(u->sink_input);
         u->sink_input = NULL;
     }
-
-    if (u->source_output) {
-        u->source_output->parent.process_msg = pa_source_output_process_msg;
-        pa_source_output_unref(u->source_output);
-        u->source_output = NULL;
-    }
 }
 
 /* Called from main context */
@@ -646,6 +652,17 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     pa_module_unload_request(u->module, TRUE);
 }
 
+/* Called from the output thread context */
+static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
+    struct userdata *u;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(u = i->userdata);
+
+    if (state == PA_SINK_INPUT_UNLINKED)
+        pa_asyncmsgq_flush(u->asyncmsgq, false);
+}
+
 /* Called from main thread */
 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
     struct userdata *u;
@@ -857,6 +874,7 @@ int pa__init(pa_module *m) {
     u->sink_input->pop = sink_input_pop_cb;
     u->sink_input->process_rewind = sink_input_process_rewind_cb;
     u->sink_input->kill = sink_input_kill_cb;
+    u->sink_input->state_change = sink_input_state_change_cb;
     u->sink_input->attach = sink_input_attach_cb;
     u->sink_input->detach = sink_input_detach_cb;
     u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;

commit ee0a5d50148ee1d99a511372ae2af2036b6612a2
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Thu Mar 14 22:07:13 2013 +0200

    filter-apply: Fix segfault with moving streams
    
    process() may be called with a stream that doesn't have its sink/source set.
    This can happen if the proplist change callback is called when the stream is
    moving.

diff --git a/src/modules/module-filter-apply.c b/src/modules/module-filter-apply.c
index 6826a0a..4e85ea1 100644
--- a/src/modules/module-filter-apply.c
+++ b/src/modules/module-filter-apply.c
@@ -417,14 +417,18 @@ static pa_hook_result_t process(struct userdata *u, pa_object *o, pa_bool_t is_s
     pa_bool_t done_something = FALSE;
     pa_sink *sink = NULL;
     pa_source *source = NULL;
-    pa_module *module;
+    pa_module *module = NULL;
 
     if (is_sink_input) {
         sink = PA_SINK_INPUT(o)->sink;
-        module = sink->module;
+
+        if (sink)
+            module = sink->module;
     } else {
         source = PA_SOURCE_OUTPUT(o)->source;
-        module = source->module;
+
+        if (source)
+            module = source->module;
     }
 
     /* If there is no sink/source yet, we can't do much */

commit f8b57af2c890f3cb98ee07ed7c0192e75146cbf1
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Thu Mar 14 22:07:12 2013 +0200

    loopback: Fix segfault in may_move_to() callbacks
    
    The sink input may_move_to() callbacks can be called while the source
    output is not connected to any source (i.e. is currently moving too),
    and vice versa.
    
    Thanks to Frédéric Dalleau for reporting this bug.

diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index 461c4a7..ea24c3b 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -379,13 +379,16 @@ static void source_output_kill_cb(pa_source_output *o) {
 }
 
 /* Called from main thread */
-static pa_bool_t source_output_may_move_to_cb(pa_source_output *o, pa_source *dest) {
+static bool source_output_may_move_to_cb(pa_source_output *o, pa_source *dest) {
     struct userdata *u;
 
     pa_source_output_assert_ref(o);
     pa_assert_ctl_context();
     pa_assert_se(u = o->userdata);
 
+    if (!u->sink_input || !u->sink_input->sink)
+        return true;
+
     return dest != u->sink_input->sink->monitor_source;
 }
 
@@ -667,15 +670,15 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
 }
 
 /* Called from main thread */
-static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
+static bool sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
     struct userdata *u;
 
     pa_sink_input_assert_ref(i);
     pa_assert_ctl_context();
     pa_assert_se(u = i->userdata);
 
-    if (!u->source_output->source->monitor_of)
-        return TRUE;
+    if (!u->source_output || !u->source_output->source)
+        return true;
 
     return dest != u->source_output->source->monitor_of;
 }



More information about the pulseaudio-commits mailing list