[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