初筛 sa-215 + 独立复核 sa-216 确认(V1 读侧缺口被复核推翻——#3087 修复实际完整;V2 真实但低危)。 ## 文件与行号 internal/im/daemon_bridge.go L1237-1241(daemonSessionTurnIndex) ## 问题描述 ```go if n := len(ses.UsageHistory); n > 0 && ses.UsageHistory[n-1].TurnIndex > last { ... if n := len(ses.Metrics); n > 0 && ses.Metrics[n-1].TurnIndex > last { ``` 裸读共享切片,未持 endpointStatsMu——而 #3087/#3086 已为跨 goroutine 读提供持锁快照访问器 `UsageHistorySnapshot()`(endpoint_stats.go L68)/`MetricsSnapshot()`(L84),此处未使用。与 append 并发时 -race 可报,极端下 torn view。 ## 触发场景 `daemonSessionTurnIndex` 唯一调用点为 `NewDaemonBridge` L120(bridge 构造期一次性),早于 collector 注册(L133)——实际并发窗口接近零,故低危。属 #3087 收尾遗漏的一致性缺口而非可复现故障。 ## 预期 vs 实际 预期:跨 goroutine 读走快照访问器(访问器注释明言此用途);实际:裸读。 ## 修复建议 两行替换:`ses.UsageHistorySnapshot()` / `ses.MetricsSnapshot()` 后取末元素(或 len==0 跳过)。 ## 严重程度 low(构造期一次性读、窗口近零;一致性收尾)
Activity
Merge pull request #3092 from topcheer/fix-3091
topcheer commentedon Oct 2, 2026
已复核确认并修复(PR #3092,已合并,CI 全绿)。
根因
daemonSessionTurnIndex(daemon_bridge.go L1237-1241)在 #3087 引入持锁快照访问器后仍保留两处裸读(len(ses.UsageHistory)+末元素、s.Metrics同型)——访问器注释明言的跨 goroutine 读用途未在此处落地。唯一调用点为 bridge 构造期一次性(早于 collector 注册),窗口近零,属 #3087 收尾遗漏的一致性缺口(issue 内 V1 读侧缺口主张已被复核正确推翻——#3087 修复本身完整)。修复
两处裸读替换为
UsageHistorySnapshot()/MetricsSnapshot()(#3086/#3087 同一锁域),max-TurnIndex 语义不变。验证
go build -tags goolm ./...+internal/im包测试 -race 模式绿zz_issue3091_test.go:nil 会话/空会话/usage 末项最大/metric 末项最大四态