queue2: fix event/preroll deadlock
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Thu, 20 Mar 2014 10:14:33 +0000 (06:14 -0400)
committerWim Taymans <wtaymans@redhat.com>
Mon, 24 Mar 2014 11:00:50 +0000 (12:00 +0100)
The qlock is released between popping a buffer from the queue
and pushing it. When this buffer causes the sink to wait in
preroll, this lets a query see that the queue is empty, and
push the query then wait for it to be serviced. However, this
will not be done till after peroll, and this will thus block.
If upstream was waiting on buffering to reach 100% before
switching to PLAYING, a deadlock would ensue.

We fix it by refusing the query when buffering, as per Wim's
recommendation on IRC.

plugins/elements/gstqueue2.c

index a03cc0c..5389681 100644 (file)
@@ -2335,8 +2335,7 @@ gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent,
          * completely, which can not happen if we block on the query..
          * Therefore we only potentially block when we are not buffering. */
         GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->sinkresult, out_flushing);
-        if (QUEUE_IS_USING_QUEUE (queue) && (gst_queue2_is_empty (queue)
-                || !queue->use_buffering)) {
+        if (QUEUE_IS_USING_QUEUE (queue) && !queue->is_buffering) {
           gst_queue2_locked_enqueue (queue, query, GST_QUEUE2_ITEM_TYPE_QUERY);
 
           STATUS (queue, queue->sinkpad, "wait for QUERY");