From f82a731b3a09f2752c0475ff6e51757b8551868a Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Fri, 7 Oct 2022 21:02:52 +0200 Subject: [PATCH] webrtcsink: fix deadlock on encoder setup Refactor connect_input_stream in order to avoid an ABBA deadlock altogether: where in other spots we lock settings then state, here we were emitting encoder-setup with state held, then locking settings in the default handler. We could have changed the locking order in the other spots, but instead we can also just release the state lock when emitting the signal, which is good practice. Fixes #108 --- plugins/src/webrtcsink/imp.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/src/webrtcsink/imp.rs b/plugins/src/webrtcsink/imp.rs index 9ecb7b863..4d5687e89 100644 --- a/plugins/src/webrtcsink/imp.rs +++ b/plugins/src/webrtcsink/imp.rs @@ -75,7 +75,7 @@ struct Settings { } /// Represents a codec we can offer -#[derive(Debug)] +#[derive(Debug, Clone)] struct Codec { encoder: gst::ElementFactory, payloader: gst::ElementFactory, @@ -1858,6 +1858,7 @@ impl WebRTCSink { fn on_remote_description_set(&self, element: &super::WebRTCSink, session_id: String) { let mut state = self.state.lock().unwrap(); let mut remove = false; + let codecs = state.codecs.clone(); if let Some(mut session) = state.sessions.remove(&session_id) { for webrtc_pad in session.webrtc_pads.clone().values() { @@ -1874,10 +1875,11 @@ impl WebRTCSink { if let Some(producer) = state .streams .get(&webrtc_pad.stream_name) - .and_then(|stream| stream.producer.as_ref()) + .and_then(|stream| stream.producer.clone()) { + drop(state); if let Err(err) = - session.connect_input_stream(element, producer, webrtc_pad, &state.codecs) + session.connect_input_stream(element, &producer, webrtc_pad, &codecs) { gst::error!( CAT, @@ -1888,8 +1890,10 @@ impl WebRTCSink { err ); remove = true; + state = self.state.lock().unwrap(); break; } + state = self.state.lock().unwrap(); } else { gst::error!( CAT,