mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-10-03 15:53:56 +00:00
fix(proc): EvtConsumer 生命周期——消除 host.Close 后的 SIGSEGV
预存缺陷(非本次重构引入,但会稳定复现崩溃): Stop() 只 close 了 stop channel,而 Run() 阻塞在 evtfd.Read 里, 根本没有机会检查 stop。调用方在 Stop 后释放 ringData(host.Close 会 munmap 整个区域),Run 一旦从 Read 恢复就会读已解除映射的内存: **SIGSEGV,recover 捕不到**。实测 TestEventRing_OverflowStillDelivers 约 50% 概率触发。 两次尝试与结论: 1. os.File.SetReadDeadline 无效——eventfd/pipe 经 os.NewFile 包装后 **不会**注册进 Go netpoller(os.NewFile 对非 open 得到的 fd 一律按 非 pollable 处理),Read 是阻塞 syscall,SetReadDeadline 返回错误。 2. 改为 poll(2) 显式加超时(evtpoll_unix.go),消费循环每 100ms 回到 stop 检查。 新增 API 契约: - Stop() 非阻塞,仅请求退出 - Wait() 阻塞至 Run 退出;**返回后才能释放 ringData** - drainEvents 每条事件后检查 stop,避免慢 handler 拖延退出 其他: - evtring_test.go 三个用例改为 defer Wait() → defer Stop()(LIFO 保证 Wait 先于 host.Close 完成) - 溢出用例的 handler 改为非阻塞投递:写入了 8292 条事件而 channel 只 消费 1 条,阻塞投递会让 drainEvents 卡在 handler 里,Stop 无法退出
This commit is contained in:
@ -34,6 +34,9 @@ func TestEventRing_BasicWriteAndConsume(t *testing.T) {
|
||||
},
|
||||
)
|
||||
go consumer.Run()
|
||||
// LIFO:先 Stop(打断阻塞的 Read)再 Wait(等 Run 退出),
|
||||
// 两者都必须在 host.Close(munmap 整个区域)之前完成。
|
||||
defer consumer.Wait()
|
||||
defer consumer.Stop()
|
||||
|
||||
// 订阅 agent_output 事件
|
||||
@ -85,11 +88,18 @@ func TestEventRing_OverflowStillDelivers(t *testing.T) {
|
||||
host.EvtfdReadFile(),
|
||||
0,
|
||||
func(evt *pubsdk.Event) error {
|
||||
received <- evt
|
||||
// 非阻塞投递:本用例写入了 8292 条事件,若这里阻塞在
|
||||
// channel 上,drainEvents 会卡在 handler 里,Stop 就无法
|
||||
// 让 Run 退出。
|
||||
select {
|
||||
case received <- evt:
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
go consumer.Run()
|
||||
defer consumer.Wait()
|
||||
defer consumer.Stop()
|
||||
|
||||
select {
|
||||
@ -125,6 +135,7 @@ func TestEventRing_TypeMaskFiltering(t *testing.T) {
|
||||
},
|
||||
)
|
||||
go consumer.Run()
|
||||
defer consumer.Wait()
|
||||
defer consumer.Stop()
|
||||
|
||||
unsub := er.Subscribe(pubsdk.EventToolCall)
|
||||
|
||||
Reference in New Issue
Block a user