fix(state_portal): prevent shutdown deadlock on full bounded channel (closes #8)
shutdown() calls enc.flush() → drain_encoder() → tx.send() on a crossbeam bounded(32) channel. If the channel is full and the receiver (webrtc_rx) is alive but not being drained, send() blocks forever — a self-deadlock since both ends belong to the same struct. Two-layer fix: - avhw.rs: replace tx.send() with tx.try_send(); handle Full (drop frame) and Disconnected (set flag) separately. - state_portal.rs: drop webrtc_rx before flushing in shutdown() so try_send returns Disconnected immediately. Regression tests added for the channel semantics.
This commit is contained in:
+16
-7
@@ -935,13 +935,22 @@ impl SwEncState {
|
||||
let data: &[u8] = unsafe {
|
||||
std::slice::from_raw_parts(raw.data, raw.size as usize)
|
||||
};
|
||||
if let Err(e) = tx.send(data.to_vec()) {
|
||||
tracing::warn!(
|
||||
"WebRTC channel send failed (receiver dropped): {} bytes lost",
|
||||
e.0.len()
|
||||
);
|
||||
self.webrtc_disconnected = true;
|
||||
break;
|
||||
match tx.try_send(data.to_vec()) {
|
||||
Ok(()) => {}
|
||||
Err(crossbeam_channel::TrySendError::Full(frame)) => {
|
||||
tracing::warn!(
|
||||
"WebRTC channel full, dropping frame: {} bytes lost",
|
||||
frame.len()
|
||||
);
|
||||
}
|
||||
Err(crossbeam_channel::TrySendError::Disconnected(frame)) => {
|
||||
tracing::warn!(
|
||||
"WebRTC channel disconnected: {} bytes lost",
|
||||
frame.len()
|
||||
);
|
||||
self.webrtc_disconnected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user