urisourcebin: Avoid deadlock on shutdown

The reason why the STATE lock was taken was to avoid issues where we would be
adding (and activating) elements at the same time as urisourcebin would be
brought down to READY. That would cause those new elements to potentially return
ERRORS because of not-negotiated/flushing-pads

But that creates a really bad deadlock (state lock is taken to deactivate the
streaming thread which .. is currently grabbing the state lock).

Instead, we can just ignore the warning/error messages that might occur when
shutting down.

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4075

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8162>
This commit is contained in:
Edward Hervey 2024-12-16 16:36:06 +01:00 committed by GStreamer Marge Bot
parent 988f806e7a
commit f7d6822589

View file

@ -2091,12 +2091,6 @@ setup_parsebin_for_slot (ChildSrcPadInfo * info, GstPad * originating_pad)
GST_DEBUG_OBJECT (urisrc, "Shutting down, returning early"); GST_DEBUG_OBJECT (urisrc, "Shutting down, returning early");
return FALSE; return FALSE;
} }
GST_STATE_LOCK (urisrc);
if (g_atomic_int_get (&urisrc->flushing)) {
GST_DEBUG_OBJECT (urisrc, "Shutting down, returning early");
GST_STATE_UNLOCK (urisrc);
return FALSE;
}
GST_URI_SOURCE_BIN_LOCK (urisrc); GST_URI_SOURCE_BIN_LOCK (urisrc);
/* Set up optional pre-parsebin download/ringbuffer elements */ /* Set up optional pre-parsebin download/ringbuffer elements */
@ -2121,7 +2115,6 @@ setup_parsebin_for_slot (ChildSrcPadInfo * info, GstPad * originating_pad)
"ring-buffer-max-size", urisrc->ring_buffer_max_size, "ring-buffer-max-size", urisrc->ring_buffer_max_size,
"max-size-buffers", 0, NULL); "max-size-buffers", 0, NULL);
} }
gst_element_set_locked_state (info->pre_parse_queue, TRUE);
gst_bin_add (GST_BIN_CAST (urisrc), info->pre_parse_queue); gst_bin_add (GST_BIN_CAST (urisrc), info->pre_parse_queue);
sinkpad = gst_element_get_static_pad (info->pre_parse_queue, "sink"); sinkpad = gst_element_get_static_pad (info->pre_parse_queue, "sink");
link_res = gst_pad_link (originating_pad, sinkpad); link_res = gst_pad_link (originating_pad, sinkpad);
@ -2136,7 +2129,6 @@ setup_parsebin_for_slot (ChildSrcPadInfo * info, GstPad * originating_pad)
post_missing_plugin_error (GST_ELEMENT_CAST (urisrc), "parsebin"); post_missing_plugin_error (GST_ELEMENT_CAST (urisrc), "parsebin");
return FALSE; return FALSE;
} }
gst_element_set_locked_state (info->demuxer, TRUE);
gst_bin_add (GST_BIN_CAST (urisrc), info->demuxer); gst_bin_add (GST_BIN_CAST (urisrc), info->demuxer);
info->demuxer_is_parsebin = TRUE; info->demuxer_is_parsebin = TRUE;
@ -2162,23 +2154,15 @@ setup_parsebin_for_slot (ChildSrcPadInfo * info, GstPad * originating_pad)
"pad-removed", G_CALLBACK (demuxer_pad_removed_cb), info); "pad-removed", G_CALLBACK (demuxer_pad_removed_cb), info);
if (info->pre_parse_queue) { if (info->pre_parse_queue) {
gst_element_set_locked_state (info->pre_parse_queue, FALSE);
gst_element_sync_state_with_parent (info->pre_parse_queue); gst_element_sync_state_with_parent (info->pre_parse_queue);
} }
gst_element_set_locked_state (info->demuxer, FALSE);
gst_element_sync_state_with_parent (info->demuxer); gst_element_sync_state_with_parent (info->demuxer);
GST_URI_SOURCE_BIN_UNLOCK (urisrc); GST_URI_SOURCE_BIN_UNLOCK (urisrc);
GST_STATE_UNLOCK (urisrc);
return TRUE; return TRUE;
could_not_link: could_not_link:
{ {
if (info->pre_parse_queue)
gst_element_set_locked_state (info->pre_parse_queue, FALSE);
if (info->demuxer)
gst_element_set_locked_state (info->demuxer, FALSE);
GST_URI_SOURCE_BIN_UNLOCK (urisrc); GST_URI_SOURCE_BIN_UNLOCK (urisrc);
GST_STATE_UNLOCK (urisrc);
GST_ELEMENT_ERROR (urisrc, CORE, NEGOTIATION, GST_ELEMENT_ERROR (urisrc, CORE, NEGOTIATION,
(NULL), ("Can't link to (pre-)parsebin element")); (NULL), ("Can't link to (pre-)parsebin element"));
return FALSE; return FALSE;
@ -3103,6 +3087,16 @@ handle_message (GstBin * bin, GstMessage * msg)
handle_buffering_message (urisrc, msg); handle_buffering_message (urisrc, msg);
msg = NULL; msg = NULL;
break; break;
case GST_MESSAGE_ERROR:
case GST_MESSAGE_WARNING:
if (g_atomic_int_get (&urisrc->flushing)) {
/* Errors/warnings when shutting down are non-critical */
GST_DEBUG_OBJECT (urisrc, "Flushing, ignoring message %" GST_PTR_FORMAT,
msg);
gst_message_unref (msg);
msg = NULL;
}
break;
default: default:
break; break;
} }