basesrc: avoid potential deadlock

In gst_base_src_start_complete() we do a perform_seek() that will eventually
start the streaming thread which acquires the live lock and then goes to sleep
in the case of appsrc. Right after we perform seek we also try to acquire the
live lock which might then deadlock.

fix this by taking the stream lock before performing the seek. This makes sure
that the streaming thread cannot start and grab the live lock until we are done
and release the stream lock again.

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=676048
This commit is contained in:
Wim Taymans 2012-05-16 09:16:26 +02:00
parent a49b9a9946
commit d6e909994c

View file

@ -3138,6 +3138,9 @@ gst_base_src_start_complete (GstBaseSrc * basesrc, GstFlowReturn ret)
mode = GST_PAD_MODE (basesrc->srcpad); mode = GST_PAD_MODE (basesrc->srcpad);
GST_OBJECT_UNLOCK (basesrc->srcpad); GST_OBJECT_UNLOCK (basesrc->srcpad);
/* take the stream lock here, we only want to let the task run when we have
* set the STARTED flag */
GST_PAD_STREAM_LOCK (basesrc->srcpad);
if (mode == GST_PAD_MODE_PUSH) { if (mode == GST_PAD_MODE_PUSH) {
/* do initial seek, which will start the task */ /* do initial seek, which will start the task */
GST_OBJECT_LOCK (basesrc); GST_OBJECT_LOCK (basesrc);
@ -3166,10 +3169,13 @@ gst_base_src_start_complete (GstBaseSrc * basesrc, GstFlowReturn ret)
GST_LIVE_SIGNAL (basesrc); GST_LIVE_SIGNAL (basesrc);
GST_LIVE_UNLOCK (basesrc); GST_LIVE_UNLOCK (basesrc);
GST_PAD_STREAM_UNLOCK (basesrc->srcpad);
return; return;
seek_failed: seek_failed:
{ {
GST_PAD_STREAM_UNLOCK (basesrc->srcpad);
GST_ERROR_OBJECT (basesrc, "Failed to perform initial seek"); GST_ERROR_OBJECT (basesrc, "Failed to perform initial seek");
gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL); gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
if (event) if (event)
@ -3179,6 +3185,7 @@ seek_failed:
} }
no_get_range: no_get_range:
{ {
GST_PAD_STREAM_UNLOCK (basesrc->srcpad);
gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL); gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
GST_ERROR_OBJECT (basesrc, "Cannot operate in pull mode, stopping"); GST_ERROR_OBJECT (basesrc, "Cannot operate in pull mode, stopping");
ret = GST_FLOW_ERROR; ret = GST_FLOW_ERROR;