fix(state_portal): make shutdown() idempotent to prevent duplicate log lines (#22)
shutdown() fired twice on exit (explicit call in main.rs + Drop impl), causing "Total: N frames" and "StatePortal shutdown complete" to log twice 23us apart. Add `shutdown_started: bool` guard at function entry. Plain bool (not AtomicBool) because &mut self already grants exclusive access. Guard is set BEFORE cleanup so Drop re-entry during panic unwinding is suppressed. Includes scripts/test_shutdown_idempotency.sh as a live regression test (requires Wayland session). Verified PASS on KWin: both lines print exactly once.
This commit is contained in:
+9
-2
@@ -66,6 +66,7 @@ pub struct StatePortal {
|
||||
last_fillable_frame: Option<CpuNv12Frame>, // cached last frame for filler duplication
|
||||
next_filler_at: Option<Instant>, // when to send next filler frame
|
||||
filler_frames_sent: u64,
|
||||
shutdown_started: bool, // idempotency guard; plain bool because &mut self is exclusive (not AtomicBool)
|
||||
}
|
||||
|
||||
impl StatePortal {
|
||||
@@ -112,6 +113,7 @@ impl StatePortal {
|
||||
last_fillable_frame: None,
|
||||
next_filler_at: None,
|
||||
filler_frames_sent: 0,
|
||||
shutdown_started: false,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -586,10 +588,15 @@ impl StatePortal {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 关闭状态:刷新编码器并清理资源
|
||||
/// 关闭状态:刷新编码器并清理资源(幂等)。
|
||||
///
|
||||
/// 使用 `enc.take()` 确保编码器只被 flush 一次,即使多次调用也安全(幂等)。
|
||||
/// `shutdown_started` 守卫在清理之前置位——防止 panic 时 `Drop` 重入 unwinding。
|
||||
pub fn shutdown(&mut self) {
|
||||
if self.shutdown_started {
|
||||
return;
|
||||
}
|
||||
self.shutdown_started = true;
|
||||
|
||||
self.last_fillable_frame = None;
|
||||
// 1. Stop encode thread (drops webrtc_tx → signals WebRTC thread to exit)
|
||||
if let Some(mut enc_thread) = self.enc_thread.take() {
|
||||
|
||||
Reference in New Issue
Block a user