bin: Make sure we don't add/remove a bin to/from itself
authorVivia Nikolaidou <vivia@toolsonair.com>
Mon, 24 Aug 2015 18:04:37 +0000 (21:04 +0300)
committerSebastian Dröge <sebastian@centricular.com>
Tue, 25 Aug 2015 07:19:44 +0000 (10:19 +0300)
Doing so would deadlock from trying to acquire the object lock twice

https://bugzilla.gnome.org/show_bug.cgi?id=754036

gst/gstbin.c
tests/check/gst/gstbin.c

index cdd585a..2813f63 100644 (file)
@@ -1290,6 +1290,7 @@ gst_bin_add (GstBin * bin, GstElement * element)
 
   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+  g_return_val_if_fail (GST_ELEMENT_CAST (bin) != element, FALSE);
 
   bclass = GST_BIN_GET_CLASS (bin);
 
@@ -1333,6 +1334,10 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
 
   GST_DEBUG_OBJECT (bin, "element :%s", GST_ELEMENT_NAME (element));
 
+  /* we obviously can't remove ourself from ourself */
+  if (G_UNLIKELY (element == GST_ELEMENT_CAST (bin)))
+    goto removing_itself;
+
   GST_OBJECT_LOCK (bin);
 
   GST_OBJECT_LOCK (element);
@@ -1564,6 +1569,13 @@ no_state_recalc:
   return TRUE;
 
   /* ERROR handling */
+removing_itself:
+  {
+    GST_OBJECT_LOCK (bin);
+    g_warning ("Cannot remove bin '%s' from itself", GST_ELEMENT_NAME (bin));
+    GST_OBJECT_UNLOCK (bin);
+    return FALSE;
+  }
 not_in_bin:
   {
     g_warning ("Element '%s' is not in bin '%s'", elem_name,
@@ -1603,6 +1615,7 @@ gst_bin_remove (GstBin * bin, GstElement * element)
 
   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+  g_return_val_if_fail (GST_ELEMENT_CAST (bin) != element, FALSE);
 
   bclass = GST_BIN_GET_CLASS (bin);
 
index 171884f..297f6b4 100644 (file)
@@ -697,7 +697,7 @@ GST_START_TEST (test_add_self)
   bin = gst_bin_new (NULL);
   fail_unless (bin != NULL, "Could not create bin");
 
-  ASSERT_WARNING (gst_bin_add (GST_BIN (bin), bin));
+  ASSERT_CRITICAL (gst_bin_add (GST_BIN (bin), bin));
 
   gst_object_unref (bin);
 }