aboutsummaryrefslogtreecommitdiffstats
path: root/src/output
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2010-11-04 21:51:02 +0100
committerMax Kellermann <max@duempel.org>2010-11-04 21:51:02 +0100
commit21223154aa3a3c794a3842aa8a5c85198ce85220 (patch)
tree54d29e4ea9a639c33915a64d92809455dfe96094 /src/output
parenta549d871f30db65da597b6d9b478dd5bab1a62f9 (diff)
downloadmpd-21223154aa3a3c794a3842aa8a5c85198ce85220.tar.gz
mpd-21223154aa3a3c794a3842aa8a5c85198ce85220.tar.xz
mpd-21223154aa3a3c794a3842aa8a5c85198ce85220.zip
output_control: lock object in audio_output_close()
Protect the attributes "open" and "fail_timer".
Diffstat (limited to '')
-rw-r--r--src/output_control.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/src/output_control.c b/src/output_control.c
index 16c0dbb75..dd562f303 100644
--- a/src/output_control.c
+++ b/src/output_control.c
@@ -50,6 +50,20 @@ static void ao_command(struct audio_output *ao, enum audio_output_command cmd)
ao_command_wait(ao);
}
+/**
+ * Like ao_command(), but assumes the object is locked by the caller.
+ */
+static void
+ao_command_locked(struct audio_output *ao, enum audio_output_command cmd)
+{
+ assert(ao->command == AO_COMMAND_NONE);
+ ao->command = cmd;
+
+ g_mutex_unlock(ao->mutex);
+ ao_command_wait(ao);
+ g_mutex_lock(ao->mutex);
+}
+
static void ao_command_async(struct audio_output *ao,
enum audio_output_command cmd)
{
@@ -162,21 +176,33 @@ void audio_output_cancel(struct audio_output *ao)
ao_command_async(ao, AO_COMMAND_CANCEL);
}
-void audio_output_close(struct audio_output *ao)
+static void
+audio_output_close_locked(struct audio_output *ao)
{
+ assert(ao != NULL);
assert(!ao->open || ao->fail_timer == NULL);
if (ao->mixer != NULL)
mixer_auto_close(ao->mixer);
if (ao->open)
- ao_command(ao, AO_COMMAND_CLOSE);
+ ao_command_locked(ao, AO_COMMAND_CLOSE);
else if (ao->fail_timer != NULL) {
g_timer_destroy(ao->fail_timer);
ao->fail_timer = NULL;
}
}
+void audio_output_close(struct audio_output *ao)
+{
+ assert(ao != NULL);
+ assert(!ao->open || ao->fail_timer == NULL);
+
+ g_mutex_lock(ao->mutex);
+ audio_output_close_locked(ao);
+ g_mutex_unlock(ao->mutex);
+}
+
void audio_output_finish(struct audio_output *ao)
{
audio_output_close(ao);