diff options
author | Max Kellermann <max@duempel.org> | 2009-03-25 17:07:15 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2009-03-25 17:07:15 +0100 |
commit | 4dbf73d88bf5ab2da154ac2f537aa28a67c5f8b6 (patch) | |
tree | 56158acb8882f2879af37ed4345dc571c272150c /src/output_all.c | |
parent | 71cd24954a34bc9fb0fdf6505616ba79b8320a5a (diff) | |
download | mpd-4dbf73d88bf5ab2da154ac2f537aa28a67c5f8b6.tar.gz mpd-4dbf73d88bf5ab2da154ac2f537aa28a67c5f8b6.tar.xz mpd-4dbf73d88bf5ab2da154ac2f537aa28a67c5f8b6.zip |
output: protect audio_output.open with the mutex
There was a deadlock between the output thread and the player thread:
when the output thread failed (and closed itself) while the player
thread worked with the audio_output object, MPD could crash.
Diffstat (limited to '')
-rw-r--r-- | src/output_all.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/src/output_all.c b/src/output_all.c index bf9202060..2e7d3a720 100644 --- a/src/output_all.c +++ b/src/output_all.c @@ -169,6 +169,19 @@ static void audio_output_wait_all(void) notify_wait(&audio_output_client_notify); } +static void +audio_output_reset_reopen(struct audio_output *ao) +{ + g_mutex_lock(ao->mutex); + + if (!ao->open && ao->fail_timer != NULL) { + g_timer_destroy(ao->fail_timer); + ao->fail_timer = NULL; + } + + g_mutex_unlock(ao->mutex); +} + /** * Resets the "reopen" flag on all audio devices. MPD should * immediately retry to open the device instead of waiting for the @@ -180,10 +193,7 @@ audio_output_all_reset_reopen(void) for (unsigned i = 0; i < num_audio_outputs; ++i) { struct audio_output *ao = &audio_outputs[i]; - if (!ao->open && ao->fail_timer != NULL) { - g_timer_destroy(ao->fail_timer); - ao->fail_timer = NULL; - } + audio_output_reset_reopen(ao); } } @@ -289,6 +299,9 @@ static bool chunk_is_consumed_in(const struct audio_output *ao, const struct music_chunk *chunk) { + if (!ao->open) + return true; + if (ao->chunk == NULL) return false; @@ -312,9 +325,6 @@ chunk_is_consumed(const struct music_chunk *chunk) const struct audio_output *ao = &audio_outputs[i]; bool consumed; - if (!ao->open) - continue; - g_mutex_lock(ao->mutex); consumed = chunk_is_consumed_in(ao, chunk); g_mutex_unlock(ao->mutex); @@ -339,14 +349,15 @@ clear_tail_chunk(G_GNUC_UNUSED const struct music_chunk *chunk, bool *locked) for (unsigned i = 0; i < num_audio_outputs; ++i) { struct audio_output *ao = &audio_outputs[i]; - locked[i] = ao->open; - - if (!locked[i]) - continue; - /* this mutex will be unlocked by the caller when it's ready */ g_mutex_lock(ao->mutex); + locked[i] = ao->open; + + if (!locked[i]) { + g_mutex_unlock(ao->mutex); + continue; + } assert(ao->chunk == chunk); assert(ao->chunk_finished); |