playsink: Fix race condition in stream synchronizer pad cleanup during state changes
Prevent race condition where gst_play_sink_do_reconfigure() could be called from a pad probe while stream synchronizer pads are being released during GST_STATE_CHANGE_PAUSED_TO_READY transition. The race occurred when: 1. State change starts releasing stream synchronizer pads 2. Pads are unblocked earlier in the state change, allowing events to flow 3. A streaming thread triggers sinkpad_blocked_cb -> gst_play_sink_do_reconfigure 4. Reconfiguration tries to use already-released pad pointers 5. New pad creation fails with assertion in gst_pad_iterate_internal_links The fix adds GST_PLAY_SINK_LOCK around the pad cleanup to ensure atomic cleanup and prevent concurrent access during state transitions. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9233>
This commit is contained in:
parent
743c425f64
commit
e799d79025
@ -5069,35 +5069,50 @@ gst_play_sink_change_state (GstElement * element, GstStateChange transition)
|
||||
playsink->need_async_start = TRUE;
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:{
|
||||
GList *pads_to_release = NULL;
|
||||
gboolean remove_audio_ssync_queue = FALSE;
|
||||
|
||||
GST_PLAY_SINK_LOCK (playsink);
|
||||
if (playsink->video_sinkpad_stream_synchronizer) {
|
||||
gst_element_release_request_pad (GST_ELEMENT_CAST
|
||||
(playsink->stream_synchronizer),
|
||||
pads_to_release = g_list_prepend (pads_to_release,
|
||||
playsink->video_sinkpad_stream_synchronizer);
|
||||
gst_object_unref (playsink->video_sinkpad_stream_synchronizer);
|
||||
pads_to_release = g_list_prepend (pads_to_release,
|
||||
playsink->video_srcpad_stream_synchronizer);
|
||||
playsink->video_sinkpad_stream_synchronizer = NULL;
|
||||
gst_object_unref (playsink->video_srcpad_stream_synchronizer);
|
||||
playsink->video_srcpad_stream_synchronizer = NULL;
|
||||
}
|
||||
if (playsink->audio_sinkpad_stream_synchronizer) {
|
||||
gst_element_release_request_pad (GST_ELEMENT_CAST
|
||||
(playsink->stream_synchronizer),
|
||||
pads_to_release = g_list_prepend (pads_to_release,
|
||||
playsink->audio_sinkpad_stream_synchronizer);
|
||||
gst_object_unref (playsink->audio_sinkpad_stream_synchronizer);
|
||||
pads_to_release = g_list_prepend (pads_to_release,
|
||||
playsink->audio_srcpad_stream_synchronizer);
|
||||
playsink->audio_sinkpad_stream_synchronizer = NULL;
|
||||
gst_object_unref (playsink->audio_srcpad_stream_synchronizer);
|
||||
playsink->audio_srcpad_stream_synchronizer = NULL;
|
||||
|
||||
gst_play_sink_remove_audio_ssync_queue (playsink);
|
||||
remove_audio_ssync_queue = TRUE;
|
||||
}
|
||||
if (playsink->text_sinkpad_stream_synchronizer) {
|
||||
gst_element_release_request_pad (GST_ELEMENT_CAST
|
||||
(playsink->stream_synchronizer),
|
||||
pads_to_release = g_list_prepend (pads_to_release,
|
||||
playsink->text_sinkpad_stream_synchronizer);
|
||||
gst_object_unref (playsink->text_sinkpad_stream_synchronizer);
|
||||
pads_to_release = g_list_prepend (pads_to_release,
|
||||
playsink->text_srcpad_stream_synchronizer);
|
||||
playsink->text_sinkpad_stream_synchronizer = NULL;
|
||||
gst_object_unref (playsink->text_srcpad_stream_synchronizer);
|
||||
playsink->text_srcpad_stream_synchronizer = NULL;
|
||||
}
|
||||
GST_PLAY_SINK_UNLOCK (playsink);
|
||||
|
||||
for (GList * l = pads_to_release; l; l = l->next) {
|
||||
GstPad *pad = GST_PAD (l->data);
|
||||
if (GST_PAD_IS_SINK (pad)) {
|
||||
gst_element_release_request_pad (GST_ELEMENT_CAST
|
||||
(playsink->stream_synchronizer), pad);
|
||||
}
|
||||
gst_object_unref (pad);
|
||||
}
|
||||
g_list_free (pads_to_release);
|
||||
|
||||
if (remove_audio_ssync_queue) {
|
||||
gst_play_sink_remove_audio_ssync_queue (playsink);
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||
|
@ -363,6 +363,7 @@ gst_stream_synchronizer_iterate_internal_links (GstPad * pad,
|
||||
GstIterator *it = NULL;
|
||||
GstPad *opad;
|
||||
|
||||
GST_STREAM_SYNCHRONIZER_LOCK (parent);
|
||||
opad =
|
||||
gst_stream_get_other_pad_from_pad (GST_STREAM_SYNCHRONIZER (parent), pad);
|
||||
if (opad) {
|
||||
@ -374,6 +375,7 @@ gst_stream_synchronizer_iterate_internal_links (GstPad * pad,
|
||||
g_value_unset (&value);
|
||||
gst_object_unref (opad);
|
||||
}
|
||||
GST_STREAM_SYNCHRONIZER_UNLOCK (parent);
|
||||
|
||||
return it;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user