From 80c5fd50dbb72a9cf3584ba0c2d9cd70a7cc90b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 18 Jan 2017 15:07:58 +0200 Subject: [PATCH] parse: Don't hold element's object lock while querying element pads' caps This can easily deadlock if the element uses the object lock for something internally, like posting an error message. Use an GstIterator for iterating over the pads instead. https://bugzilla.gnome.org/show_bug.cgi?id=777449 --- gst/parse/grammar.y | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/gst/parse/grammar.y b/gst/parse/grammar.y index 5111903047..6a958c99e2 100644 --- a/gst/parse/grammar.y +++ b/gst/parse/grammar.y @@ -587,32 +587,44 @@ static gboolean gst_parse_element_can_do_caps (GstElement * e, GstPadDirection dir, GstCaps * link_caps) { - gboolean can_do = FALSE; - GList *pads; + gboolean can_do = FALSE, done = FALSE; + GstIterator *it; - GST_OBJECT_LOCK (e); + it = (dir == GST_PAD_SRC) ? gst_element_iterate_src_pads (e) : gst_element_iterate_sink_pads (e); - pads = (dir == GST_PAD_SRC) ? e->srcpads : e->sinkpads; - - while (!can_do && pads != NULL) { - GstPad *pad = pads->data; + while (!done && !can_do) { + GValue v = G_VALUE_INIT; + GstPad *pad; GstCaps *caps; - caps = gst_pad_get_current_caps (pad); - if (caps == NULL) - caps = gst_pad_query_caps (pad, NULL); + switch (gst_iterator_next (it, &v)) { + case GST_ITERATOR_OK: + pad = g_value_get_object (&v); - can_do = gst_caps_can_intersect (caps, link_caps); + caps = gst_pad_get_current_caps (pad); + if (caps == NULL) + caps = gst_pad_query_caps (pad, NULL); - GST_TRACE ("can_do: %d for %" GST_PTR_FORMAT " and %" GST_PTR_FORMAT, - can_do, caps, link_caps); + can_do = gst_caps_can_intersect (caps, link_caps); - gst_caps_unref (caps); + GST_TRACE ("can_do: %d for %" GST_PTR_FORMAT " and %" GST_PTR_FORMAT, + can_do, caps, link_caps); - pads = pads->next; + gst_caps_unref (caps); + + g_value_unset (&v); + break; + case GST_ITERATOR_DONE: + case GST_ITERATOR_ERROR: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + } } - GST_OBJECT_UNLOCK (e); + gst_iterator_free (it); return can_do; }