summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pulsecore/sink-input.c3
-rw-r--r--src/pulsecore/sink.c7
-rw-r--r--src/pulsecore/sink.h6
-rw-r--r--src/pulsecore/source-output.c3
-rw-r--r--src/pulsecore/source.c5
-rw-r--r--src/pulsecore/source.h6
6 files changed, 27 insertions, 3 deletions
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 8ec63b5da..843297f6c 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -1538,6 +1538,9 @@ bool pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
if (dest == i->sink)
return true;
+ if (dest->unlink_requested)
+ return false;
+
if (!pa_sink_input_may_move(i))
return false;
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 0b44fc726..3f1ef725b 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -676,9 +676,10 @@ void pa_sink_unlink(pa_sink* s) {
* reversing pa_sink_put(). It also undoes the registrations
* already done in pa_sink_new()! */
- /* All operations here shall be idempotent, i.e. pa_sink_unlink()
- * may be called multiple times on the same sink without bad
- * effects. */
+ if (s->unlink_requested)
+ return;
+
+ s->unlink_requested = true;
linked = PA_SINK_IS_LINKED(s->state);
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 5df109e55..b64a6665a 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -63,6 +63,12 @@ struct pa_sink {
pa_core *core;
pa_sink_state_t state;
+
+ /* Set in the beginning of pa_sink_unlink() before setting the sink state
+ * to UNLINKED. The purpose is to prevent moving streams to a sink that is
+ * about to be removed. */
+ bool unlink_requested;
+
pa_sink_flags_t flags;
pa_suspend_cause_t suspend_cause;
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 9217ad462..6d54ae826 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -1187,6 +1187,9 @@ bool pa_source_output_may_move_to(pa_source_output *o, pa_source *dest) {
if (dest == o->source)
return true;
+ if (dest->unlink_requested)
+ return false;
+
if (!pa_source_output_may_move(o))
return false;
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index f4b96ab88..98374ae92 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -618,6 +618,11 @@ void pa_source_unlink(pa_source *s) {
/* See pa_sink_unlink() for a couple of comments how this function
* works. */
+ if (s->unlink_requested)
+ return;
+
+ s->unlink_requested = true;
+
linked = PA_SOURCE_IS_LINKED(s->state);
if (linked)
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 19fb41bd5..91e8674b7 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -64,6 +64,12 @@ struct pa_source {
pa_core *core;
pa_source_state_t state;
+
+ /* Set in the beginning of pa_source_unlink() before setting the source
+ * state to UNLINKED. The purpose is to prevent moving streams to a source
+ * that is about to be removed. */
+ bool unlink_requested;
+
pa_source_flags_t flags;
pa_suspend_cause_t suspend_cause;