summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Raghavan <arun@accosted.net>2014-09-29 20:18:08 +0530
committerSebastian Dröge <sebastian@centricular.com>2014-10-14 09:28:43 +0200
commit6279f682e8749c793f95d93fb37e9e7bbcb09cb2 (patch)
tree3dcaf990a7862e3b33ae3ee6449b32de31bc4e76
parentd52a618b498cf4e65e57d841d6eeba73e8a36670 (diff)
pulsesink: Make emitting stream status messages synchronous
The stream status messages are emitted in the PA mainloop thread, which means the mainloop lock is taken, followed by the Gst object lock (by gst_element_post_message()). In all other locations, the order of locking is reversed (this is unavoidable in a bunch of cases where the object lock is taken by GstBaseSink or GstAudioBaseSink, and then we get control to take the mainloop lock). The only way to guarantee that the defer callback for stream status messages doesn't deadlock is to either stop posting those messages, or make sure that the message emission is completed before we proceed to any point that might take the object lock before the mainloop lock (which is what we do after this patch). https://bugzilla.gnome.org/show_bug.cgi?id=736071
-rw-r--r--ext/pulse/pulsesink.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
index e580afce2..e77ce8d5e 100644
--- a/ext/pulse/pulsesink.c
+++ b/ext/pulse/pulsesink.c
@@ -1209,6 +1209,14 @@ gst_pulseringbuffer_start (GstAudioRingBuffer * buf)
g_atomic_int_get (&GST_AUDIO_BASE_SINK (psink)->eos_rendering))
gst_pulsering_set_corked (pbuf, FALSE, FALSE);
+ /* Wait for the stream status message to be posted. This needs to be done
+ * synchronously because the callback will take the mainloop lock
+ * (implicitly) and then take the GST_OBJECT_LOCK. Everywhere else, we take
+ * the locks in the reverse order, so not doing this synchronously could
+ * cause a deadlock. */
+ GST_DEBUG_OBJECT (psink, "waiting for stream status (ENTER) to be posted");
+ pa_threaded_mainloop_wait (mainloop);
+
pa_threaded_mainloop_unlock (mainloop);
return TRUE;
@@ -1315,6 +1323,14 @@ cleanup:
pa_mainloop_api_once (pa_threaded_mainloop_get_api (mainloop),
mainloop_leave_defer_cb, psink);
+ /* Wait for the stream status message to be posted. This needs to be done
+ * synchronously because the callback will take the mainloop lock
+ * (implicitly) and then take the GST_OBJECT_LOCK. Everywhere else, we take
+ * the locks in the reverse order, so not doing this synchronously could
+ * cause a deadlock. */
+ GST_DEBUG_OBJECT (psink, "waiting for stream status (LEAVE) to be posted");
+ pa_threaded_mainloop_wait (mainloop);
+
pa_threaded_mainloop_unlock (mainloop);
return res;