After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 702840 - queue2 does not work with use-buffering=true
queue2 does not work with use-buffering=true
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-base
git master
Other Linux
: Normal blocker
: 1.1.2
Assigned To: GStreamer Maintainers
GStreamer Maintainers
: 703354 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2013-06-21 22:46 UTC by Youness Alaoui
Modified: 2014-03-24 11:06 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Fix event/preroll deadlock (4.01 KB, patch)
2014-03-20 10:26 UTC, Vincent Penquerc'h
none Details | Review
Fix event/preroll deadlock (1.60 KB, patch)
2014-03-20 12:15 UTC, Vincent Penquerc'h
none Details | Review

Description Youness Alaoui 2013-06-21 22:46:06 UTC
For some reason, uridecodebin does not work anymore for audio/video from an http source in the git version of gst 1.0. These for example do not work on 1.0 :
  gst-launch-1.0 uridecodebin uri="http://download.wavetlan.com/SVV/Media/HTTP/H264/Talkinghead_Media/H264_test1_Talkinghead_mp4_480x360.mp4" name=d  ! videoconvert ! xvimagesink  d. ! pulsesink
  gst-launch-1.0 uridecodebin uri="http://people.collabora.com/~kakaroto/MP3-320-CBR-NS/01 Rhiannon.mp3" ! pulsesink
The same command works if I use gst-launch-0.10 instead of gst-launch-1.0. Also note that an HLS stream (http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8) works.
If I use playbin instead of uridecodebin, it works, if I use 'souphttpsrc ! queue2 ! decodebin', it works as well, but if I use "souphttpsrc ! queue2 use-buffering=true ! decodebin" then it stops working.

From my observations, it looks like queue2 sends the buffering 0% message then stops doing anything, blocking this way forever. 
If I also set ring-buffer-max-size to something like 1000000, it works, but setting it to the default of 0 will not work. This is weird though since it works with playbin and playbin also uses ring-buffer-max-size with a default of 0.
This is a regression in git since with 1.0.7, it works, but it fails with the git version.
Comment 1 Wim Taymans 2013-06-24 21:14:57 UTC
It's caused by adding support for serialized queries. 

* queue2 is blocked pushing a buffer downstream because the sink is blocking in preroll
* The basesrc is doing an allocation query that blocks waiting for a reply that never comes because the pushing side it blocked.

I think the best thing for now is to only forward the serialized query when:

 - The queue is empty, so you know nothing is blocking downstream
 - *or* The queue is not buffering
Comment 2 Wim Taymans 2013-06-24 21:32:47 UTC
commit 2f78e962997725f734353ffe5c061f98b53903d8
Author: Wim Taymans <wim.taymans@collabora.co.uk>
Date:   Mon Jun 24 23:25:51 2013 +0200

    queue2: only block serialized query when it's safe
    
    We must be certain that we don't cause a deadlock when blocking the serialized
    queries. One such deadlock can happen when we are buffering and downstream is
    blocked in preroll and a serialized query arrives. Downstream will not unblock
    (and allow our query to execute) until we complete buffering and buffering will
    not complete until we can answer the query..
    
    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702840
Comment 3 Sebastian Dröge (slomo) 2013-06-30 16:34:23 UTC
Why is this not a problem in queue and multiqueue when they emit BUFFERING messages and are blocked downstream?
Comment 4 Sebastian Dröge (slomo) 2013-06-30 17:08:23 UTC
*** Bug 703354 has been marked as a duplicate of this bug. ***
Comment 5 Sebastian Dröge (slomo) 2013-07-16 09:39:21 UTC
commit 0dc232e1140be953e920388c54dd4cfa0d7637e0
Author: Sebastian Dröge <slomo@circular-chaos.org>
Date:   Tue Jul 16 11:36:50 2013 +0200

    multiqueue: only block serialized query when it's safe
    
    We must be certain that we don't cause a deadlock when blocking the serialized
    queries. One such deadlock can happen when we are buffering and downstream is
    blocked in preroll and a serialized query arrives. Downstream will not unblock
    (and allow our query to execute) until we complete buffering and buffering will
    not complete until we can answer the query..
    
    https://bugzilla.gnome.org/show_bug.cgi?id=702840
Comment 6 Vincent Penquerc'h 2014-03-19 21:50:36 UTC
I think this might be not quite enough. I've been tracking down a deadlock in a situation where I have a souphttpsrc, queue2, then other stuff ending in a multiudpsink. Not always, I get a deadlock with:
- one thread blocked in preroll, where queue2 has pushed a buffer, and multiudpsink is then blocked in preroll
- one thread gets a sink query, checks if it's using queue (yes), if the queue is empty (yes), so enqueues the query and waits.

What seems to be happening is that the qlock is released after dequeuing the buffer, so the queue will be empty while the buffer is making its way downstream, so the query can be pushed, and this blocks.

A naive idea would be to only dequeue the buffer (or event, etc) after it's been pushed.

Does this seem plausible/sane ?
Comment 7 Vincent Penquerc'h 2014-03-20 10:26:25 UTC
Created attachment 272474 [details] [review]
Fix event/preroll deadlock

This "works for me". It avoids waiting on the event when downstream may block. It waits on all buffers and buffer lists, which may be a bit too much, and denies request then. This seems "violent", but this is also what the existing code does, so may be OK. Sane enough ?
Comment 8 Vincent Penquerc'h 2014-03-20 12:15:26 UTC
Created attachment 272477 [details] [review]
Fix event/preroll deadlock

As discussed with Wim on IRC, new simpler version.
Comment 9 Wim Taymans 2014-03-24 11:06:27 UTC
commit a6decb91ac2c035c381d59f1f1fabfeb2f869f95
Author: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Date:   Thu Mar 20 06:14:33 2014 -0400

    queue2: fix event/preroll deadlock
    
    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.