[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