webrtcbin: Fix potential deadlock on bin elements cleanup
authorEmil Ljungdahl <emillj@axis.com>
Fri, 15 Nov 2024 14:00:00 +0000 (15:00 +0100)
committerEmil Ljungdahl <emillj@axis.com>
Tue, 17 Dec 2024 09:48:46 +0000 (09:48 +0000)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7900>

subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c

index cb77d3db588bfc737e34c8ea666442462cb44cfe..8e3b9a90d7f806875ab60471c9b6b98148462190 100644 (file)
@@ -2630,12 +2630,11 @@ _on_data_channel_ready_state (WebRTCDataChannel * channel,
     if (found == FALSE) {
       GST_FIXME_OBJECT (webrtc, "Received close for unknown data channel");
     } else {
-      gst_element_set_locked_state (channel->src_bin, TRUE);
-      gst_element_set_state (channel->src_bin, GST_STATE_NULL);
+      /* Take an extra ref to src & sink bins so that teardown can be made outside dc_lock */
+      gst_object_ref (channel->src_bin);
       gst_bin_remove (GST_BIN (webrtc), channel->src_bin);
 
-      gst_element_set_locked_state (channel->sink_bin, TRUE);
-      gst_element_set_state (channel->sink_bin, GST_STATE_NULL);
+      gst_object_ref (channel->sink_bin);
       gst_bin_remove (GST_BIN (webrtc), channel->sink_bin);
 
       if (found_pending == FALSE) {
@@ -2643,6 +2642,17 @@ _on_data_channel_ready_state (WebRTCDataChannel * channel,
       }
     }
     DC_UNLOCK (webrtc);
+
+    if (found == TRUE) {
+      /* Tear down bins outside dc_lock to avoid deadlocks */
+      gst_element_set_locked_state (channel->src_bin, TRUE);
+      gst_element_set_state (channel->src_bin, GST_STATE_NULL);
+      gst_object_unref (channel->src_bin);
+
+      gst_element_set_locked_state (channel->sink_bin, TRUE);
+      gst_element_set_state (channel->sink_bin, GST_STATE_NULL);
+      gst_object_unref (channel->sink_bin);
+    }
   }
 }