base: Fix pad callbacks so they handle when parent goes away
authorOle André Vadla Ravnås <oravnas@cisco.com>
Thu, 6 Jan 2011 17:11:31 +0000 (18:11 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 13 Apr 2011 15:39:05 +0000 (17:39 +0200)
1) We need to lock and get a strong ref to the parent, if still there.
2) If it has gone away, we need to handle that gracefully.

This is necessary in order to safely modify a running pipeline. Has been
observed when a streaming thread is doing a buffer_alloc() while an
application thread sends an event on a pad further downstream, and from
within a pad probe (holding STREAM_LOCK) carries out the pipeline plumbing
while the streaming thread has its buffer_alloc() in progress.

libs/gst/base/gstbasesink.c
libs/gst/base/gstbasetransform.c

index 01900ed..7740a77 100644 (file)
@@ -653,6 +653,8 @@ gst_base_sink_pad_buffer_alloc (GstPad * pad, guint64 offset, guint size,
   GstFlowReturn result = GST_FLOW_OK;
 
   bsink = GST_BASE_SINK (gst_pad_get_parent (pad));
+  if (G_UNLIKELY (bsink == NULL))
+    return GST_FLOW_WRONG_STATE;
   bclass = GST_BASE_SINK_GET_CLASS (bsink);
 
   if (bclass->buffer_alloc)
@@ -3414,6 +3416,10 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
   GstBaseSinkClass *bclass;
 
   basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
+  if (G_UNLIKELY (basesink == NULL)) {
+    gst_event_unref (event);
+    return FALSE;
+  }
 
   bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
index 8875336..4a0e24f 100644 (file)
@@ -1225,8 +1225,13 @@ static gboolean
 gst_base_transform_query (GstPad * pad, GstQuery * query)
 {
   gboolean ret = FALSE;
-  GstBaseTransform *trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-  GstPad *otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
+  GstBaseTransform *trans;
+  GstPad *otherpad;
+
+  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+  if (G_UNLIKELY (trans == NULL))
+    return FALSE;
+  otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_POSITION:{
@@ -1715,6 +1720,8 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
   guint size_suggest;
 
   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+  if (G_UNLIKELY (trans == NULL))
+    return GST_FLOW_WRONG_STATE;
   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   priv = trans->priv;
 
@@ -1997,6 +2004,10 @@ gst_base_transform_sink_event (GstPad * pad, GstEvent * event)
   gboolean forward = TRUE;
 
   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+  if (G_UNLIKELY (trans == NULL)) {
+    gst_event_unref (event);
+    return FALSE;
+  }
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   if (bclass->event)