aggregator: Take lock to ensure set_caps is not called concurently
authorThibault Saunier <tsaunier@gnome.org>
Fri, 3 Oct 2014 10:34:15 +0000 (12:34 +0200)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 2 Dec 2017 15:10:25 +0000 (15:10 +0000)
Avoiding to be in an inconsistent state where we do not have
actual negotiate caps set as srccaps and leading to point where we
try to unref ->srccaps when they have already been set to NULL.

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

libs/gst/base/gstaggregator.c

index bc53044..8f53512 100644 (file)
@@ -106,6 +106,22 @@ GST_DEBUG_CATEGORY_STATIC (aggregator_debug);
   g_cond_broadcast(&(((GstAggregatorPad* )pad)->priv->event_cond)); \
   }
 
+#define GST_AGGREGATOR_SETCAPS_LOCK(self)   G_STMT_START {        \
+  GST_LOG_OBJECT (self, "Taking SETCAPS lock from thread %p",   \
+        g_thread_self());                                         \
+  g_mutex_lock(&self->priv->setcaps_lock);                         \
+  GST_LOG_OBJECT (self, "Took SETCAPS lock from thread %p",     \
+        g_thread_self());                                         \
+  } G_STMT_END
+
+#define GST_AGGREGATOR_SETCAPS_UNLOCK(self)   G_STMT_START {        \
+  GST_LOG_OBJECT (self, "Releasing SETCAPS lock from thread %p",  \
+        g_thread_self());                                           \
+  g_mutex_unlock(&self->priv->setcaps_lock);                         \
+  GST_LOG_OBJECT (self, "Took SETCAPS lock from thread %p",       \
+        g_thread_self());                                           \
+  } G_STMT_END
+
 struct _GstAggregatorPadPrivate
 {
   gboolean pending_flush_start;
@@ -177,6 +193,9 @@ struct _GstAggregatorPrivate
 
   GstTagList *tags;
   gboolean tags_changed;
+
+  /* Lock to prevent two src setcaps from happening at the same time  */
+  GMutex setcaps_lock;
 };
 
 typedef struct
@@ -347,8 +366,10 @@ _push_mandatory_events (GstAggregator * self)
 void
 gst_aggregator_set_src_caps (GstAggregator * self, GstCaps * caps)
 {
+  GST_AGGREGATOR_SETCAPS_LOCK (self);
   gst_caps_replace (&self->priv->srccaps, caps);
   _push_mandatory_events (self);
+  GST_AGGREGATOR_SETCAPS_UNLOCK (self);
 }
 
 /**
@@ -1053,6 +1074,7 @@ gst_aggregator_finalize (GObject * object)
   GstAggregator *self = (GstAggregator *) object;
 
   g_mutex_clear (&self->priv->mcontext_lock);
+  g_mutex_clear (&self->priv->setcaps_lock);
 
   G_OBJECT_CLASS (aggregator_parent_class)->finalize (object);
 }
@@ -1134,6 +1156,7 @@ gst_aggregator_init (GstAggregator * self, GstAggregatorClass * klass)
   gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
 
   g_mutex_init (&self->priv->mcontext_lock);
+  g_mutex_init (&self->priv->setcaps_lock);
 }
 
 /* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init