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 473846 - Deadlock if sink is unable to send first buffer
Deadlock if sink is unable to send first buffer
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gstreamer (core)
0.10.13
Other All
: Normal normal
: 0.10.15
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2007-09-05 09:07 UTC by Johan Gyllenspetz
Modified: 2007-09-05 22:16 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Johan Gyllenspetz 2007-09-05 09:07:23 UTC
Please describe the problem:
Unlock function is not called on a sink that sink is based on basesink. This occurs when that sink is added to an pipeline that is already in PLAY state (the sink is brought up to PLAY before it is added) and the sink is unable to pass on its first buffer (i.e. it never returns).

Steps to reproduce:
1. Add a source to a pipeline
2. Set the pipeline to PLAYING state
3. Create a sink (based on basesink) that does not return in render.
4. Set the state of the sink to PLAYING
5. Add sink to pipeline.
6. Try to set state of pipeline to NULL
7. App will hang on STATE_LOCK


Actual results:
1. The GST_PAD_PREROLL_LOCK for the sink is taken in gst_base_sink_chain, initiated by a gst_pad_push.
2. Since the sink is unable to push its first buffer the lock will not be released.
3. The GST_STATE_LOCK for the pipeline is taken in gst_bin_continue_func which then performs a latency query and then hangs on the sinks GST_PAD_PREROLL_LOCK (taken in 1.).
4. When the state is changed to NULL the gst_element_set_state_func will hang on on the previously taken GST_STATE_LOCK.

Expected results:
A deadlock occurs.

Does this happen every time?
yes

Other information:
/*
 * A small test application that simulates the bug with an fdsink writing more
 * then 64K to a pipe and therefore blocks the first buffer.
 */

#include <gst/gst.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int
main (int   argc,
      char *argv[])
{
  GstStateChangeReturn sret;
  GstElement *pipeline;
  GstElement *source, *sink;
  gint fd;

  gst_init (&argc, &argv);

  if (unlink("test")) {
    perror("unlink:");
  }

  if (mkfifo("test", O_CREAT|S_IRWXU)) {
    perror("mkfifo:");
  }

  fd = open("test", O_RDWR);

  pipeline = gst_pipeline_new ("pipeline");

  source = gst_element_factory_make ("fakesrc", "source");

  g_object_set (G_OBJECT (source), "num-buffers", 5, NULL);
  g_object_set (G_OBJECT (source), "sizetype", 2, NULL);
  g_object_set (G_OBJECT (source), "filltype", 4, NULL);
  g_object_set (G_OBJECT (source), "sizemax", 70000, NULL);

  gst_bin_add (GST_BIN (pipeline), source);

  sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);

  sink = gst_element_factory_make ("fdsink", "sink");
  g_object_set (G_OBJECT (sink), "fd",
		fd,
		NULL);

  gst_bin_add (GST_BIN (pipeline), sink);

  gst_element_set_state (sink, GST_STATE_PLAYING);

  gst_element_link (source, sink);

  /* To make sure that the deadlock occurs */
  sleep (4);

  gst_element_set_state (pipeline, GST_STATE_NULL);

  return 0;
}
Comment 1 Wim Taymans 2007-09-05 22:16:10 UTC
two problems with this program:

1) you start playback of the source before it is linked, this causes an error if you don't manage to link the sink fast enough.

2) the fd passed to fdsink is not set to NONBLOCK, this currently makes the write call block (and not cancelable) forever.

I think you just want to make a pipeline, set it to PLAYING, then perform a latency query and see it deadlock.

I changed core to not take the PREROLL lock anymore when doing the query. 

        * libs/gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_flush),
        (gst_base_sink_wait_preroll), (gst_base_sink_needs_preroll),
        (gst_base_sink_query):
        Protect eos and have_preroll with the OBJECT lock so we don't need to
        take the PREROLL lock when querying the latency. Fixes #473846.