diff --git a/gst/gstbin.c b/gst/gstbin.c index e5d4ecd4c4bb020a6302a414c88e470abad4ca74..d9060c84c0e5ce04f0f6a1a5c723cec2f867211b 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -1864,6 +1864,19 @@ gst_bin_remove (GstBin * bin, GstElement * element) if (G_UNLIKELY (bclass->remove_element == NULL)) goto no_function; + /* We need to take the state lock here to ensure that we're + * not currently just before setting the state of this child + * element. Otherwise it can happen that we removed the element + * here and e.g. set it to NULL state, and shortly afterwards + * have another thread set it to a higher state again as part of + * a state change for the whole bin. + * + * When adding an element to the bin this is not needed as we + * require callers to always ensure after adding to the bin that + * the new element is set to the correct state. + */ + GST_STATE_LOCK (bin); + GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s", GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin)); @@ -1871,6 +1884,8 @@ gst_bin_remove (GstBin * bin, GstElement * element) result = bclass->remove_element (bin, element); GST_TRACER_BIN_REMOVE_POST (bin, result); + GST_STATE_UNLOCK (bin); + return result; /* ERROR handling */ diff --git a/gst/gstelement.c b/gst/gstelement.c index 4078fa7219a3de9ecf18523f03746461fe33755c..e186a09353c68a47149ac73982d768be2f645271 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -2241,6 +2241,10 @@ gst_element_is_locked_state (GstElement * element) * Locks the state of an element, so state changes of the parent don't affect * this element anymore. * + * Note that this is racy if the state lock of the parent bin is not taken. + * The parent bin might've just checked the flag in another thread and as the + * next step proceed to change the child element's state. + * * MT safe. * * Returns: %TRUE if the state was changed, %FALSE if bad parameters were given