From 8ec5d0995f8759cfb67fc54a691254b9d1ee4c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Laignel?= Date: Wed, 13 Aug 2025 18:45:38 +0200 Subject: [PATCH] rtprecv: fix race condition on first buffer When an incoming buffer is received, a deadlock can occur if: 1. 1st buffer is currently being handled by the src pad's task => holds semaphore. 2. 1st buffer reaches downstream AudioDecoder => Latency query. 3. src pad's task still holding semaphore while relaying Latency query. 4. `src_query()` calls `Pad::default()` which calls `iterate_internal_links()`. 5. `iterate_internal_links()` tries to acquire the `state` `Mutex` which is already locked by `handle_push_jitterbuffer()`. This commit temporarily releases the `state` `Mutex` until the semaphore is acquired. Part-of: --- net/rtp/src/rtpbin2/rtprecv.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/rtp/src/rtpbin2/rtprecv.rs b/net/rtp/src/rtpbin2/rtprecv.rs index 7ff7dd2fa..ff3dcd6b9 100644 --- a/net/rtp/src/rtpbin2/rtprecv.rs +++ b/net/rtp/src/rtpbin2/rtprecv.rs @@ -1201,9 +1201,18 @@ impl RtpRecv { // FIXME: Should block if too many packets are stored here because the source pad task // is blocked + // Make sure not to deadlock, e.g.: + // 1. 1st buffer is currently being handled by the src pad's task => holds semaphore. + // 2. 1st buffer reaches downstream AudioDecoder => Latency query. + // 3. src pad's task still holding semaphore while relaying Latency query. + // 4. `src_query()` calls `Pad::default()` which calls `iterate_internal_links()`. + // 5. `iterate_internal_links()` tries to acquire the `state` `Mutex`. + // => deadlock. + drop(state); let _src_pad_permit = rtpbin2::get_or_init_runtime() .expect("initialized in change_state()") .block_on(buffer.recv_src_pad.semaphore.acquire()); + state = self.state.lock().unwrap(); let mut jb_store = buffer.recv_src_pad.jitter_buffer_store.lock().unwrap();