From b3df4dc2c92d27034eaf9cef52e97a6e39c77d2e Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 23 Aug 2011 22:43:08 +0200 Subject: output/pulse: fix deadlock when the stream was suspended Check if the stream is suspended; wake up the main loop when it becomes suspended. --- NEWS | 1 + src/output/pulse_output_plugin.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) 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) { -- cgit v1.2.3