Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2022-09-27 12:22:36 +0300
committerSebastian Dröge <sebastian@centricular.com>2022-09-27 12:54:21 +0300
commitb6ebad27614287ed122a9080f0c7955b056316b6 (patch)
treefd3e94fb68ba6140d6859102eddda45e642774a9 /utils
parentadb4cb86918176c34f4942795305a017416f73c7 (diff)
fallbackswitch: Fix lock order problem between state and stream lock
The order is first stream lock, then state lock. Everything else can lead to deadlocks.
Diffstat (limited to 'utils')
-rw-r--r--utils/fallbackswitch/src/fallbackswitch/imp.rs55
1 files changed, 37 insertions, 18 deletions
diff --git a/utils/fallbackswitch/src/fallbackswitch/imp.rs b/utils/fallbackswitch/src/fallbackswitch/imp.rs
index 8567ac2b1..a75aa32fb 100644
--- a/utils/fallbackswitch/src/fallbackswitch/imp.rs
+++ b/utils/fallbackswitch/src/fallbackswitch/imp.rs
@@ -759,12 +759,19 @@ impl FallbackSwitch {
return Ok(gst::FlowSuccess::Ok);
}
+ // Lock order: First stream lock then state lock!
+ let _stream_lock = MutexGuard::unlocked(&mut state, || self.src_pad.stream_lock());
+
+ is_active = self.active_sinkpad.lock().as_ref() == Some(pad);
+ if !is_active {
+ log!(CAT, obj: pad, "Dropping {:?} on inactive pad", buffer);
+ return Ok(gst::FlowSuccess::Ok);
+ }
+
let switched_pad = state.switched_pad;
let discont_pending = state.discont_pending;
state.switched_pad = false;
state.discont_pending = false;
-
- let _stream_lock = self.src_pad.stream_lock();
drop(state);
if switched_pad {
@@ -855,7 +862,6 @@ impl FallbackSwitch {
}
let mut state = self.state.lock();
- let forward = self.active_sinkpad.lock().as_ref() == Some(pad);
let mut pad_state = pad.imp().state.lock();
@@ -901,30 +907,43 @@ impl FallbackSwitch {
_ => {}
}
- let fwd_sticky = if forward && state.switched_pad && event.is_serialized() {
+ drop(pad_state);
+
+ let mut is_active = self.active_sinkpad.lock().as_ref() == Some(pad);
+ if !is_active {
+ log!(CAT, obj: pad, "Dropping {:?} on inactive pad", event);
+ return true;
+ }
+
+ // Lock order: First stream lock then state lock!
+ let stream_lock_for_serialized = event
+ .is_serialized()
+ .then(|| MutexGuard::unlocked(&mut state, || self.src_pad.stream_lock()));
+
+ is_active = self.active_sinkpad.lock().as_ref() == Some(pad);
+ if !is_active {
+ log!(CAT, obj: pad, "Dropping {:?} on inactive pad", event);
+ return true;
+ }
+
+ let fwd_sticky = if state.switched_pad && stream_lock_for_serialized.is_some() {
state.switched_pad = false;
true
} else {
false
};
-
- drop(pad_state);
- let _stream_lock = forward.then(|| self.src_pad.stream_lock());
drop(state);
- if forward {
- if fwd_sticky {
- let _ = pad.push_event(gst::event::Reconfigure::new());
- pad.sticky_events_foreach(|event| {
- self.src_pad.push_event(event.clone());
- std::ops::ControlFlow::Continue(gst::EventForeachAction::Keep)
- });
+ if fwd_sticky {
+ let _ = pad.push_event(gst::event::Reconfigure::new());
+ pad.sticky_events_foreach(|event| {
+ self.src_pad.push_event(event.clone());
+ std::ops::ControlFlow::Continue(gst::EventForeachAction::Keep)
+ });
- element.notify(PROP_ACTIVE_PAD);
- }
- self.src_pad.push_event(event);
+ element.notify(PROP_ACTIVE_PAD);
}
- true
+ self.src_pad.push_event(event)
}
fn sink_query(