From 8b0b4ff0860ea93850c2f44e72e8a8a5de05e13b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 1 Sep 2011 07:13:21 +0200 Subject: output_thread: reimplement CANCEL synchronization The output thread could hang indefinitely after finishing CANCEL, because it could have missed the signal while the output was not unlocked in ao_command_finished(). This patch removes the wait() call after CANCEL, and adds the flag "allow_play" instead. While this flag is set, playback is skipped. With this flag, there will not be any excess wait() call after the pipe has been cleared. This patch fixes a bug that causes mpd to discontinue playback after seeking, due to the race condition described above. --- src/output_all.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/output_all.c') diff --git a/src/output_all.c b/src/output_all.c index 19c0f0166..551736a41 100644 --- a/src/output_all.c +++ b/src/output_all.c @@ -206,15 +206,18 @@ static void audio_output_wait_all(void) } /** - * Signals the audio output if it is open. This function locks the - * mutex. + * Signal the audio output if it is open, and set the "allow_play" + * flag. This function locks the mutex. */ static void audio_output_lock_signal(struct audio_output *ao) { g_mutex_lock(ao->mutex); + + ao->allow_play = true; if (audio_output_is_open(ao)) g_cond_signal(ao->cond); + g_mutex_unlock(ao->mutex); } -- cgit v1.2.3 From 2be6184c8d274a5b99cc2c8c86a7aebe46187320 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 1 Sep 2011 07:53:42 +0200 Subject: output_all: move _lock_signal() to output_control.c Better name, better documentation. --- src/output_all.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) (limited to 'src/output_all.c') diff --git a/src/output_all.c b/src/output_all.c index 551736a41..4e0b2eb22 100644 --- a/src/output_all.c +++ b/src/output_all.c @@ -205,30 +205,14 @@ static void audio_output_wait_all(void) notify_wait(&audio_output_client_notify); } -/** - * Signal the audio output if it is open, and set the "allow_play" - * flag. This function locks the mutex. - */ -static void -audio_output_lock_signal(struct audio_output *ao) -{ - g_mutex_lock(ao->mutex); - - ao->allow_play = true; - if (audio_output_is_open(ao)) - g_cond_signal(ao->cond); - - g_mutex_unlock(ao->mutex); -} - /** * Signals all audio outputs which are open. */ static void -audio_output_signal_all(void) +audio_output_allow_play_all(void) { for (unsigned i = 0; i < num_audio_outputs; ++i) - audio_output_lock_signal(&audio_outputs[i]); + audio_output_allow_play(&audio_outputs[i]); } static void @@ -533,7 +517,7 @@ audio_output_all_cancel(void) /* the audio outputs are now waiting for a signal, to synchronize the cleared music pipe */ - audio_output_signal_all(); + audio_output_allow_play_all(); /* invalidate elapsed_time */ -- cgit v1.2.3