aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2011-08-23 22:43:08 +0200
committerMax Kellermann <max@duempel.org>2011-08-23 23:02:13 +0200
commitb3df4dc2c92d27034eaf9cef52e97a6e39c77d2e (patch)
tree6a372b5331f6ed6402e1d2d2fd4ca07af780ddc9
parent3db9ab82ea792fbfa398d0d631f976fa33a564fe (diff)
downloadmpd-b3df4dc2c92d27034eaf9cef52e97a6e39c77d2e.tar.gz
mpd-b3df4dc2c92d27034eaf9cef52e97a6e39c77d2e.tar.xz
mpd-b3df4dc2c92d27034eaf9cef52e97a6e39c77d2e.zip
output/pulse: fix deadlock when the stream was suspended
Check if the stream is suspended; wake up the main loop when it becomes suspended.
-rw-r--r--NEWS1
-rw-r--r--src/output/pulse_output_plugin.c31
2 files changed, 32 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index eaa8d194e..b23c4a087 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ ver 0.16.4 (2011/??/??)
- alsa: fix SIGFPE when alsa announces a period size of 0
- httpd: don't warn on client disconnect
- pulse: fix deadlock when resuming the stream
+ - pulse: fix deadlock when the stream was suspended
ver 0.16.3 (2011/06/04)
diff --git a/src/output/pulse_output_plugin.c b/src/output/pulse_output_plugin.c
index c0633b9fb..babb8e221 100644
--- a/src/output/pulse_output_plugin.c
+++ b/src/output/pulse_output_plugin.c
@@ -412,6 +412,23 @@ pulse_output_wait_connection(struct pulse_output *po, GError **error_r)
}
}
+#if PA_CHECK_VERSION(0,9,8)
+
+static void
+pulse_output_stream_suspended_cb(G_GNUC_UNUSED pa_stream *stream, void *userdata)
+{
+ struct pulse_output *po = userdata;
+
+ assert(stream == po->stream || po->stream == NULL);
+ assert(po->mainloop != NULL);
+
+ /* wake up the main loop to break out of the loop in
+ pulse_output_play() */
+ pa_threaded_mainloop_signal(po->mainloop, 0);
+}
+
+#endif
+
static void
pulse_output_stream_state_cb(pa_stream *stream, void *userdata)
{
@@ -508,6 +525,11 @@ pulse_output_open(void *data, struct audio_format *audio_format,
return false;
}
+#if PA_CHECK_VERSION(0,9,8)
+ pa_stream_set_suspended_callback(po->stream,
+ pulse_output_stream_suspended_cb, po);
+#endif
+
pa_stream_set_state_callback(po->stream,
pulse_output_stream_state_cb, po);
pa_stream_set_write_callback(po->stream,
@@ -719,6 +741,15 @@ pulse_output_play(void *data, const void *chunk, size_t size, GError **error_r)
/* wait until the server allows us to write */
while (po->writable == 0) {
+#if PA_CHECK_VERSION(0,9,8)
+ if (pa_stream_is_suspended(po->stream)) {
+ pa_threaded_mainloop_unlock(po->mainloop);
+ g_set_error(error_r, pulse_output_quark(), 0,
+ "suspended");
+ return 0;
+ }
+#endif
+
pa_threaded_mainloop_wait(po->mainloop);
if (pa_stream_get_state(po->stream) != PA_STREAM_READY) {