mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-09-01 09:13:48 +00:00
threadshare: standalone rtprecv example: fix deadlock
Consider the following sequence: 1. The pipeline is being started. This occurs under the main thread. 2. A source just pushed a buffer. This occured under a ts-Context thread, let's call it ts-ctx-1. 3. The above buffer reaches `rtprecv`, which creates a src pad, which calls the 'pad-added' callback (under ts-ctx-1). 4. The 'pad-added' callback adds elements, link them and sync their state with the pipeline (under ts-ctx-1). A deadlock can occur if: A. The pipeline on-going starting process picks an element that was just added by `pad-added`, but not synced yet => the pipeline acquires the element's mutex (under the main thread). B. 'pad-added' reaches `sync_with_parent()` for the element => tries to acquire the element's mutex (under ts-ctx-1). C. The `prepare()` method for the element attempts to spawn a ts-Task on ts-ctx-1, which is blocked. So the ts-Task spawned notification is not triggered. D. Because the `prepare()` method was executed on the main thread, which is not a ts-Context thread, the ts-Task spawned notification is awaited synchronously. So the element state transition is blocked, keeping the element mutex, keeping ts-ctx-1 blocked. I couldn't find an easy way to automatically detect these conditions. The workaround here is to use a different ts-Context for the elements which are added in 'pad-added', their ts-Tasks will be spawned on a ts-Context which can't to be blocked by the starting process. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2518>
This commit is contained in:
parent
f553bd6495
commit
ac86e0590e
1 changed files with 4 additions and 2 deletions
|
@ -112,6 +112,8 @@ fn main() {
|
|||
return;
|
||||
}
|
||||
|
||||
let sub_ctx_name = format!("standalone {}.sub", i % args.groups);
|
||||
|
||||
let depay = gst::ElementFactory::make("rtpL16depay")
|
||||
.name(format!("depay-{i}").as_str())
|
||||
.build()
|
||||
|
@ -119,7 +121,7 @@ fn main() {
|
|||
|
||||
let queue = gst::ElementFactory::make("ts-queue")
|
||||
.name(format!("queue-sink-{i}").as_str())
|
||||
.property("context", &ctx_name)
|
||||
.property("context", &sub_ctx_name)
|
||||
.property("context-wait", args.wait)
|
||||
.property("max-size-buffers", 0u32)
|
||||
.property("max-size-bytes", 0u32)
|
||||
|
@ -132,7 +134,7 @@ fn main() {
|
|||
|
||||
let sink = gst::ElementFactory::make(args.sink.element_name())
|
||||
.name(format!("sink-{i}").as_str())
|
||||
.property("context", &ctx_name)
|
||||
.property("context", &sub_ctx_name)
|
||||
.property("context-wait", args.wait)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
|
Loading…
Reference in a new issue