[pulseaudio-discuss] [PATCH] core: Don't let moving filter sources/sinks become the default source/sink

Georg Chini georg at chini.tk
Mon May 8 07:31:22 UTC 2017


When a virtual sink is loaded and there is only one sound card, then during
a profile switch, all sinks and sources can become temporarily unavailable.
In that situation, the virtual sink will become the default sink, although
it is not connected to a master sink due to the move operation initiated by
the profile switch. If module-always sink is loaded, it will load a null-sink
in that situation. If also module-switch-on-connect is present, it will change
the default sink to the new null sink and try to move the sink-inputs from the
virtual sink to the null sink. This leads to a segfault because the master
sink of the virtual sink is invalid.

This patch fixes the issue by disallowing a moving virtual sink to become the
default sink.

It also fixes a bug in module-switch-on-connect, which assumed that default_sink
is always set.

The same applies to the source side.

The is_filter_{sink,source}_moving() functions were stolen from one of Tanu's
previous unapplied patches.

Buglink: https://bugs.freedesktop.org/show_bug.cgi?id=100277
---
 src/modules/module-switch-on-connect.c | 12 ++++++++++
 src/pulsecore/core.c                   | 42 ++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/src/modules/module-switch-on-connect.c b/src/modules/module-switch-on-connect.c
index 776c923e..e2da7222 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -75,6 +75,12 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void*
             return PA_HOOK_OK;
     }
 
+    /* No default sink, nothing to move away, just set the new default */
+    if (!c->default_sink) {
+        pa_core_set_configured_default_sink(c, sink);
+        return PA_HOOK_OK;
+    }
+
     if (c->default_sink == sink)
         return PA_HOOK_OK;
 
@@ -135,6 +141,12 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
             return PA_HOOK_OK;
     }
 
+    /* No default source, nothing to move away, just set the new default */
+    if (!c->default_source) {
+        pa_core_set_configured_default_source(c, source);
+        return PA_HOOK_OK;
+    }
+
     if (c->default_source == source)
         return PA_HOOK_OK;
 
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 52e51db1..99043033 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -258,6 +258,23 @@ void pa_core_set_configured_default_source(pa_core *core, pa_source *source) {
     pa_core_update_default_source(core);
 }
 
+/* Test if a sink is a moving filter sink */
+static bool is_filter_sink_moving(pa_sink *s) {
+    pa_sink *sink = s;
+
+    if (!sink)
+        return false;
+
+    while (sink->input_to_master) {
+        sink = sink->input_to_master->sink;
+
+        if (!sink)
+            return true;
+    }
+
+    return false;
+}
+
 /* a  < b  ->  return -1
  * a == b  ->  return  0
  * a  > b  ->  return  1 */
@@ -314,6 +331,10 @@ void pa_core_update_default_sink(pa_core *core) {
             best = sink;
     }
 
+    /* A moving filter sink cannot be the default sink */
+    if (is_filter_sink_moving(best))
+        best = NULL;
+
     old_default_sink = core->default_sink;
 
     if (best == old_default_sink)
@@ -332,6 +353,23 @@ void pa_core_update_default_sink(pa_core *core) {
     pa_hook_fire(&core->hooks[PA_CORE_HOOK_DEFAULT_SINK_CHANGED], core->default_sink);
 }
 
+/* Test if a source is a moving filter source */
+static bool is_filter_source_moving(pa_source *o) {
+    pa_source *source = o;
+
+    if (!source)
+        return false;
+
+    while (source->output_from_master) {
+        source = source->output_from_master->source;
+
+        if (!source)
+            return true;
+    }
+
+    return false;
+}
+
 /* a  < b  ->  return -1
  * a == b  ->  return  0
  * a  > b  ->  return  1 */
@@ -398,6 +436,10 @@ void pa_core_update_default_source(pa_core *core) {
             best = source;
     }
 
+    /* A moving filter source cannot be the default source */
+    if (is_filter_source_moving(best))
+        best = NULL;
+
     old_default_source = core->default_source;
 
     if (best == old_default_source)
-- 
2.11.0



More information about the pulseaudio-discuss mailing list