input-selector: Take the object lock while iterating sinkpads

Otherwise we can race with pad removal and crash from use-after-free.

Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1717
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3745>
This commit is contained in:
Jan Alexander Steffens (heftig) 2023-01-18 16:07:39 +01:00 committed by GStreamer Marge Bot
parent 81b726344e
commit b0e55caf0d

@ -506,18 +506,21 @@ static gboolean
gst_input_selector_all_eos (GstInputSelector * sel) gst_input_selector_all_eos (GstInputSelector * sel)
{ {
GList *walk; GList *walk;
gboolean ret = TRUE;
GST_OBJECT_LOCK (sel);
for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = walk->next) { for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = walk->next) {
GstSelectorPad *selpad; GstSelectorPad *selpad;
selpad = GST_SELECTOR_PAD_CAST (walk->data); selpad = GST_SELECTOR_PAD_CAST (walk->data);
if (!selpad->eos) { if (!selpad->eos) {
return FALSE; ret = FALSE;
break;
} }
} }
GST_OBJECT_UNLOCK (sel);
return TRUE; return ret;
} }
static gboolean static gboolean
@ -900,6 +903,7 @@ gst_input_selector_debug_cached_buffers (GstInputSelector * sel)
if (gst_debug_category_get_threshold (input_selector_debug) < GST_LEVEL_DEBUG) if (gst_debug_category_get_threshold (input_selector_debug) < GST_LEVEL_DEBUG)
return; return;
GST_OBJECT_LOCK (sel);
for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = walk->next) { for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = walk->next) {
GstSelectorPad *selpad; GstSelectorPad *selpad;
GString *timestamps; GString *timestamps;
@ -921,6 +925,7 @@ gst_input_selector_debug_cached_buffers (GstInputSelector * sel)
GST_DEBUG_OBJECT (selpad, "%s", timestamps->str); GST_DEBUG_OBJECT (selpad, "%s", timestamps->str);
g_string_free (timestamps, TRUE); g_string_free (timestamps, TRUE);
} }
GST_OBJECT_UNLOCK (sel);
} }
#endif #endif
@ -967,6 +972,8 @@ gst_input_selector_cleanup_old_cached_buffers (GstInputSelector * sel,
return; return;
GST_DEBUG_OBJECT (sel, "Cleaning up old cached buffers"); GST_DEBUG_OBJECT (sel, "Cleaning up old cached buffers");
GST_OBJECT_LOCK (sel);
for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) { for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) {
GstSelectorPad *selpad; GstSelectorPad *selpad;
GstSelectorPadCachedBuffer *cached_buffer; GstSelectorPadCachedBuffer *cached_buffer;
@ -1030,6 +1037,7 @@ gst_input_selector_cleanup_old_cached_buffers (GstInputSelector * sel,
selpad->cached_buffers = NULL; selpad->cached_buffers = NULL;
} }
} }
GST_OBJECT_UNLOCK (sel);
#if DEBUG_CACHED_BUFFERS #if DEBUG_CACHED_BUFFERS
gst_input_selector_debug_cached_buffers (sel); gst_input_selector_debug_cached_buffers (sel);
@ -1979,6 +1987,7 @@ gst_input_selector_reset (GstInputSelector * sel)
sel->eos_sent = FALSE; sel->eos_sent = FALSE;
/* reset each of our sinkpads state */ /* reset each of our sinkpads state */
GST_OBJECT_LOCK (sel);
for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) { for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) {
GstSelectorPad *selpad = GST_SELECTOR_PAD_CAST (walk->data); GstSelectorPad *selpad = GST_SELECTOR_PAD_CAST (walk->data);
@ -1989,6 +1998,8 @@ gst_input_selector_reset (GstInputSelector * sel)
selpad->tags = NULL; selpad->tags = NULL;
} }
} }
GST_OBJECT_UNLOCK (sel);
sel->have_group_id = TRUE; sel->have_group_id = TRUE;
sel->upstream_latency = 0; sel->upstream_latency = 0;
sel->last_output_ts = GST_CLOCK_TIME_NONE; sel->last_output_ts = GST_CLOCK_TIME_NONE;