osxaudio: Fix lockup in _audio_unit_property_listener
authorIlya Konstantinov <ilya.konstantinov@gmail.com>
Sat, 21 Mar 2015 18:34:25 +0000 (20:34 +0200)
committerArun Raghavan <git@arunraghavan.net>
Tue, 14 Jul 2015 12:19:50 +0000 (17:49 +0530)
_audio_unit_property_listener is called either from a Core Audio thread
or as a result of a Core Audio API (e.g. AudioUnitInitialize)
from our own thread. In the latter case, osxbuf can be already locked
(GStreamer's mutex is not recursive).

We introduce the flag cached_caps_valid and use it instead of nullifying
cached_caps when we cannot lock on osxbuf.

https://bugzilla.gnome.org/show_bug.cgi?id=743758

sys/osxaudio/gstosxaudiosink.c
sys/osxaudio/gstosxaudiosrc.c
sys/osxaudio/gstosxcoreaudio.c
sys/osxaudio/gstosxcoreaudio.h

index cfd7913..b0a3431 100644 (file)
@@ -344,7 +344,7 @@ gst_osx_audio_sink_getcaps (GstBaseSink * sink, GstCaps * filter)
   /* protect against cached_caps going away */
   GST_OBJECT_LOCK (buf);
 
-  if (osxbuf->core_audio->cached_caps) {
+  if (osxbuf->core_audio->cached_caps_valid) {
     GST_LOG_OBJECT (sink, "Returning cached caps");
     caps = gst_caps_ref (osxbuf->core_audio->cached_caps);
   } else if (buf->open) {
index 692461b..0deda90 100644 (file)
@@ -265,7 +265,7 @@ gst_osx_audio_src_get_caps (GstBaseSrc * src, GstCaps * filter)
   /* protect against cached_caps going away */
   GST_OBJECT_LOCK (buf);
 
-  if (osxbuf->core_audio->cached_caps) {
+  if (osxbuf->core_audio->cached_caps_valid) {
     GST_LOG_OBJECT (src, "Returning cached caps");
     caps = gst_caps_ref (osxbuf->core_audio->cached_caps);
   } else if (buf->open) {
index 666846c..52ac480 100644 (file)
@@ -49,6 +49,7 @@ gst_core_audio_init (GstCoreAudio * core_audio)
   core_audio->is_src = FALSE;
   core_audio->audiounit = NULL;
   core_audio->cached_caps = NULL;
+  core_audio->cached_caps_valid = FALSE;
 #ifndef HAVE_IOS
   core_audio->hog_pid = -1;
   core_audio->disabled_mixing = FALSE;
@@ -83,10 +84,13 @@ _audio_unit_property_listener (void *inRefCon, AudioUnit inUnit,
          * as needed.
          * This merely "refreshes" our PREFERRED caps. */
 
-        /* protect against cached_caps going away */
-        GST_OBJECT_LOCK (core_audio->osxbuf);
-        gst_caps_replace (&core_audio->cached_caps, NULL);
-        GST_OBJECT_UNLOCK (core_audio->osxbuf);
+        /* This function is called either from a Core Audio thread
+         * or as a result of a Core Audio API (e.g. AudioUnitInitialize)
+         * from our own thread. In the latter case, osxbuf can be
+         * already locked (GStreamer's mutex is not recursive).
+         * For this reason we use a boolean flag instead of nullifying
+         * cached_caps. */
+        core_audio->cached_caps_valid = FALSE;
       }
       break;
   }
@@ -128,6 +132,7 @@ gst_core_audio_close (GstCoreAudio * core_audio)
       core_audio);
 
   /* core_audio->osxbuf is already locked at this point */
+  core_audio->cached_caps_valid = FALSE;
   gst_caps_replace (&core_audio->cached_caps, NULL);
 
   AudioComponentInstanceDispose (core_audio->audiounit);
@@ -140,6 +145,10 @@ gst_core_audio_open (GstCoreAudio * core_audio)
 {
   OSStatus status;
 
+  /* core_audio->osxbuf is already locked at this point */
+  core_audio->cached_caps_valid = FALSE;
+  gst_caps_replace (&core_audio->cached_caps, NULL);
+
   if (!gst_core_audio_open_impl (core_audio))
     return FALSE;
 
index 71be235..fce85d0 100644 (file)
@@ -88,6 +88,7 @@ struct _GstCoreAudio
   gboolean is_src;
   gboolean is_passthrough;
   AudioDeviceID device_id;
+  gboolean cached_caps_valid; /* thread-safe flag */
   GstCaps *cached_caps;
   gint stream_idx;
   gboolean io_proc_active;