fix(webrtc): propagate poll_output error as cleanup signal to prevent zombie state (closes #14)

This commit is contained in:
dailz
2026-06-06 21:48:38 +08:00
parent e6e05fb44a
commit f3da1e4e6c

View File

@@ -246,8 +246,14 @@ impl WebRtcState {
}
pub fn write_h264_frame(&mut self, data: &[u8], frame_number: u64, fps: u32) -> Result<()> {
if let Some(inner) = self.inner.as_mut() {
inner.write_h264_frame(data, frame_number, fps)?;
let should_destroy = if let Some(inner) = self.inner.as_mut() {
inner.write_h264_frame(data, frame_number, fps)?
} else {
false
};
if should_destroy {
tracing::warn!("WebRTC connection failed during write; clearing connection state");
self.inner = None;
}
Ok(())
}
@@ -379,7 +385,8 @@ impl WebRtcInner {
Ok(Output::Timeout(_t)) => break,
Err(e) => {
tracing::error!("rtc.poll_output error: {e}");
break;
self.connected = false;
return Ok(true);
}
}
}
@@ -423,23 +430,23 @@ impl WebRtcInner {
Ok(())
}
fn write_h264_frame(&mut self, data: &[u8], frame_number: u64, fps: u32) -> Result<()> {
fn write_h264_frame(&mut self, data: &[u8], frame_number: u64, fps: u32) -> Result<bool> {
if !self.connected {
return Ok(());
return Ok(false);
}
let mid = match self.video_mid {
Some(m) => m,
None => {
tracing::warn!("write_h264: no video_mid");
return Ok(());
return Ok(false);
}
};
let pt = match self.video_pt {
Some(p) => p,
None => {
tracing::warn!("write_h264: no video_pt");
return Ok(());
return Ok(false);
}
};
@@ -449,7 +456,7 @@ impl WebRtcInner {
"write_h264: skipping non-IDR frame ({} bytes), waiting for keyframe",
data.len()
);
return Ok(());
return Ok(false);
}
tracing::info!(
"write_h264: got IDR keyframe ({} bytes), starting playback",
@@ -468,7 +475,7 @@ impl WebRtcInner {
Some(w) => w,
None => {
tracing::warn!("write_h264: no writer for mid={mid}");
return Ok(());
return Ok(false);
}
};
@@ -482,9 +489,9 @@ impl WebRtcInner {
.write(pt, Instant::now(), rtp_time, data)
.map_err(|e| anyhow::anyhow!("writer.write: {e}"))?;
self.poll_rtc()?;
let should_destroy = self.poll_rtc()?;
Ok(())
Ok(should_destroy)
}
fn is_connected(&self) -> bool {