Bug: shutdown() 中 tx.send() 阻塞导致潜在死锁 (state_portal.rs) #8
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
位置
src/state_portal.rs:287-306严重性
🔴 高
问题描述
shutdown()调用enc.flush()→drain_encoder()时,会通过tx.send()(阻塞调用)向 webrtc channel 发送编码帧。但shutdown()中并未调用poll_webrtc()来消费webrtc_rx,如果 channel 缓冲区(容量 32)已满,send()将无限阻塞,导致 Drop 期间死锁。shutdown()在Drop::drop中被调用,在析构期间阻塞特别危险——可能导致进程无法正常退出。建议修复
在
shutdown()中,先调用poll_webrtc()排空 channel,再进行enc.flush(),并在 flush 后再次 drain:test
修复方案 (commit
36f07c9)Bug 已确认并修复,双重防护:
根因分析
shutdown()→enc.flush()→drain_encoder()→tx.send()在满的bounded(32)通道上阻塞。由于webrtc_rx由同一个StatePortal持有且shutdown()中不会调用poll_webrtc()消费 receiver,导致自死锁。修复内容
avhw.rs:tx.send()→tx.try_send(),区分Full(丢帧+warn)和Disconnected(标记断连)两种失败state_portal.rs:shutdown()中 flush 前self.webrtc_rx = None,使 try_send 立即返回Disconnected回归测试
新增 3 个测试验证通道语义:
try_send_full_channel_returns_full_not_block— 满通道不阻塞try_send_after_rx_dropped_returns_disconnected— receiver drop 后立即返回shutdown_rx_drop_prevents_deadlock_on_full_channel— 满通道+drop receiver 组合场景审核过程
state.rs不存在相同问题(无 shutdown/flush 路径)