[PATCH 1/3] coreaudio: fix possible deadlock on pause
Carola Nitz
nitz.carola at googlemail.com
Fri Dec 8 17:46:01 CET 2017
ca_Pause() will now wakeup ca_Flush() or ca_Play().
Added locking between b_paused and do_flush in order to fix a deadlock.
---
modules/audio_output/coreaudio_common.c | 23 ++++++++++++++++++++++-
modules/audio_output/coreaudio_common.h | 1 +
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/modules/audio_output/coreaudio_common.c b/modules/audio_output/coreaudio_common.c
index d2e846587a..483e8e986b 100644
--- a/modules/audio_output/coreaudio_common.c
+++ b/modules/audio_output/coreaudio_common.c
@@ -50,7 +50,9 @@ ca_Open(audio_output_t *p_aout)
atomic_init(&p_sys->i_underrun_size, 0);
atomic_init(&p_sys->b_paused, false);
atomic_init(&p_sys->b_do_flush, false);
+
vlc_sem_init(&p_sys->flush_sem, 0);
+ vlc_mutex_init(&p_sys->lock);
p_aout->play = ca_Play;
p_aout->pause = ca_Pause;
@@ -62,7 +64,7 @@ void
ca_Close(audio_output_t *p_aout)
{
struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
-
+ vlc_mutex_destroy(&p_sys->lock);
vlc_sem_destroy(&p_sys->flush_sem);
}
@@ -140,13 +142,23 @@ ca_Flush(audio_output_t *p_aout, bool wait)
FramesToUs(p_sys, BytesToFrames(p_sys, i_bytes)) + 10000;
msleep(i_frame_us / 2);
+
+ if (atomic_load(&p_sys->b_paused))
+ return;
}
}
else
{
/* Request the renderer to flush, and wait for an ACK */
+ vlc_mutex_lock(&p_sys->lock);
assert(!atomic_load(&p_sys->b_do_flush));
+ if (atomic_load(&p_sys->b_paused))
+ {
+ vlc_mutex_unlock(&p_sys->lock);
+ return;
+ }
atomic_store_explicit(&p_sys->b_do_flush, true, memory_order_release);
+ vlc_mutex_unlock(&p_sys->lock);
vlc_sem_wait(&p_sys->flush_sem);
}
}
@@ -157,7 +169,16 @@ ca_Pause(audio_output_t * p_aout, bool pause, mtime_t date)
struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
VLC_UNUSED(date);
+ vlc_mutex_lock(&p_sys->lock);
atomic_store_explicit(&p_sys->b_paused, pause, memory_order_relaxed);
+
+ bool expected = true;
+ if (pause && atomic_compare_exchange_strong(&p_sys->b_do_flush, &expected, false))
+ {
+ /* Signal that the renderer is flushed */
+ vlc_sem_post(&p_sys->flush_sem);
+ }
+ vlc_mutex_unlock(&p_sys->lock);
}
void
diff --git a/modules/audio_output/coreaudio_common.h b/modules/audio_output/coreaudio_common.h
index 6719db6580..ce57ca53ea 100644
--- a/modules/audio_output/coreaudio_common.h
+++ b/modules/audio_output/coreaudio_common.h
@@ -55,6 +55,7 @@ struct aout_sys_common
atomic_uint i_underrun_size;
atomic_bool b_paused;
atomic_bool b_do_flush;
+ vlc_mutex_t lock;
vlc_sem_t flush_sem;
int i_rate;
unsigned int i_bytes_per_frame;
--
2.13.5 (Apple Git-94)
More information about the vlc-devel
mailing list