JianFeeeee
0c959e3ff3
fix(rtchild): pump 裸读写 data race —— 锁贯彻到底
## 缺陷(-race 实测)
rtChild 里 pump 是**唯一**"构造后被改写、又有并发读者"的字段,
但它的读写绕过了 rc.mu:
Dispose(StopRTChild 的 goroutine) rc.pump = nil ← 写
rtEmit (rtLoop 的 goroutine) rc.pump ← 读
-race 栈:
Read at … core.(*Agent).rtEmit rtchild.go:1275
Previous write … core.(*rtChild).Dispose rtchild.go:377
## 为什么之前没被发现
TestRTChild_E2E_Sustained 覆盖同一个窗口,但它是**偶发命中**:
全量负载下 5 次中 1 次,单跑 20 次 0 次,基线 af17af5 全量 0 次。
这种形状在 CI 里等于没有 —— 红了是运气,绿了不代表安全。
## 修法:锁贯彻到底(不是只补这一处)
rtChild 全部字段逐个判定过:
字段 构造后写? 遵守锁规?
pump 是(Dispose) ★ 本提交修:读写都持 rc.mu
light/mainRO 是(Dispose) ✓ 无并发读者,只在 Dispose 内用
slot/input/output/agent 否 ✓ 只读,不需要锁
history 是(append) ✓ 三处访问全部持锁(原有)
round/lastSeq/curCancel/critical/suppressedCancels ✓ 原本就持锁
即:pump 是唯一的漏网者,其余要么本已正确、要么根本没有并发写。
## 两个顺序要求(不只是"加个锁")
① **取走并置 nil 在锁内,Close 在锁外**
pump.Close() 内部 wg.Wait() 等消费 goroutine 收尾;持锁等待可能与
另一个持锁路径交叉。而"置 nil"必须与读者的"读"互斥,否则读者会
拿到一个已被清掉的指针。
② **rtEmit 锁内取、锁外 Push**
Push 在队列满时会阻塞,持锁会卡死 Dispose 的置 nil。
## 判据(2 条,2 次变异全部实测变红)
TestRTPumpAccessIsLocked
一边不停 emit、一边 Dispose,用 -race 判定。
变异 A(rtEmit 裸读) ⇒ 连跑 3 次全部命中 DATA RACE
变异 B(Dispose 裸写) ⇒ 第 1 次命中 DATA RACE
TestRTPumpAfterDisposeIsNil
钉住顺序语义:Dispose 之后 rc.pump 必须为 nil(否则 emit 会推
送到已关闭的 pump),且兜底路径不 panic。
## 判据第一版是假的(记下来)
第一版读者写的是 `for i := 0; i < 500; i++` —— 500 次 emit 微秒级跑完,
而写者 sleep 1ms 才动手,两者**根本不重叠**。变异 B(裸写)连跑 6 次
都不红。改成"持续跑到写者宣布结束"之后才真正抓到。
这正是「判据必须能变红」的意义:不跑变异就永远不知道它是真判据还是摆设。
## 判据的边界(诚实说明)
这条判据的"红"依赖 -race 检测器。不带 -race 时它只能发现 panic/死锁。
所以必须与 `go test -race` 一起跑 —— 提交纪律第 4 条已要求全量 -race,
这里只是把「哪个窗口最危险」钉成可复跑的形态。
## 验证(提交纪律四项全绿)
go build ./... 0
go vet ./... 0
gofmt -l internal/ cmd/ pkg/ 干净
go test ./... -count=1 -race 0 竞态,62 包全过
干净检出(worktree) build + TestRTPump 全绿
2026-11-04 16:53:13 +08:00
..
2026-11-04 08:35:23 +08:00
2026-10-29 23:53:48 +08:00
2026-10-29 23:53:48 +08:00
2026-10-29 23:53:48 +08:00
2026-11-04 11:57:48 +08:00
2026-10-29 23:53:48 +08:00
2026-10-22 20:49:44 +08:00
2026-10-29 23:53:48 +08:00
2026-10-29 23:53:48 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 08:56:47 +08:00
2026-10-21 12:17:19 +08:00
2026-10-17 19:18:24 +08:00
2026-11-04 08:21:15 +08:00
2026-10-29 23:53:48 +08:00
2026-10-21 12:17:19 +08:00
2026-11-04 11:57:48 +08:00
2026-10-27 15:53:49 +08:00
2026-10-29 23:53:48 +08:00
2026-10-29 23:53:48 +08:00
2026-11-04 16:34:46 +08:00
2026-10-26 20:55:25 +08:00
2026-10-26 20:55:25 +08:00
2026-11-04 11:57:48 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-11-04 11:57:48 +08:00
2026-11-04 11:57:48 +08:00
2026-11-03 08:46:46 +08:00
2026-11-04 11:57:48 +08:00
2026-10-21 12:17:19 +08:00
2026-10-29 23:53:48 +08:00
2026-10-29 23:53:48 +08:00
2026-11-04 11:57:48 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 08:21:15 +08:00
2026-10-29 23:53:48 +08:00
2026-10-25 13:37:29 +08:00
2026-10-25 21:39:12 +08:00
2026-10-30 17:00:47 +08:00
2026-10-25 13:48:35 +08:00
2026-11-03 14:37:53 +08:00
2026-11-04 11:57:48 +08:00
2026-10-29 23:53:48 +08:00
2026-11-04 11:57:48 +08:00
2026-11-04 11:57:48 +08:00
2026-10-29 23:53:48 +08:00
2026-10-25 15:55:26 +08:00
2026-10-25 15:55:26 +08:00
2026-10-29 23:53:48 +08:00
2026-10-25 15:55:26 +08:00
2026-11-04 11:57:48 +08:00
2026-10-29 23:53:48 +08:00
2026-10-21 12:17:19 +08:00
2026-10-29 23:53:48 +08:00
2026-10-29 23:53:48 +08:00
2026-10-26 20:55:25 +08:00
2026-10-27 12:16:06 +08:00
2026-11-04 15:58:22 +08:00
2026-11-04 15:58:22 +08:00
2026-10-21 12:17:19 +08:00
2026-10-27 15:40:43 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 08:21:15 +08:00
2026-10-21 12:17:19 +08:00
2026-10-25 17:03:09 +08:00
2026-10-26 20:55:25 +08:00
2026-11-04 11:57:48 +08:00
2026-10-22 22:42:02 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 08:21:15 +08:00
2026-11-02 21:54:35 +08:00
2026-11-02 21:54:35 +08:00
2026-11-03 14:37:53 +08:00
2026-10-21 12:17:19 +08:00
2026-11-04 11:57:48 +08:00
2026-10-26 20:55:25 +08:00
2026-10-21 12:17:19 +08:00
2026-11-04 16:34:46 +08:00
2026-11-04 16:34:46 +08:00
2026-10-29 23:53:48 +08:00
2026-10-30 17:00:47 +08:00
2026-10-21 12:17:19 +08:00
2026-11-04 14:15:33 +08:00
2026-10-29 23:53:48 +08:00
2026-10-26 20:55:25 +08:00
2026-10-29 23:53:48 +08:00
2026-11-04 11:23:05 +08:00
2026-11-04 11:23:05 +08:00
2026-10-23 15:51:02 +08:00
2026-10-27 11:49:26 +08:00
2026-11-04 08:21:15 +08:00
2026-10-23 15:51:02 +08:00
2026-10-21 12:17:19 +08:00
2026-10-06 09:22:12 +08:00
2026-10-29 23:53:48 +08:00
2026-10-31 11:39:13 +08:00
2026-10-23 15:51:02 +08:00
2026-11-04 14:15:33 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 11:57:48 +08:00
2026-10-31 06:35:32 +08:00
2026-11-04 11:23:05 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 16:53:13 +08:00
2026-10-30 17:00:47 +08:00
2026-10-30 17:00:47 +08:00
2026-10-31 19:16:58 +08:00
2026-10-30 17:00:47 +08:00
2026-10-30 17:00:47 +08:00
2026-11-04 08:21:15 +08:00
2026-10-31 10:03:43 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 16:53:13 +08:00
2026-10-25 18:25:37 +08:00
2026-10-29 23:53:48 +08:00
2026-10-21 12:17:19 +08:00
2026-10-23 15:51:02 +08:00
2026-09-13 08:59:15 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-26 20:55:25 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-09-13 07:00:51 +08:00
2026-10-24 14:34:24 +08:00
2026-10-21 12:17:19 +08:00
2026-10-27 15:58:55 +08:00
2026-11-04 11:57:48 +08:00
2026-11-04 11:57:48 +08:00
2026-11-04 11:57:48 +08:00
2026-11-03 09:20:04 +08:00
2026-10-31 07:14:09 +08:00
2026-11-04 11:57:48 +08:00
2026-10-29 23:53:48 +08:00
2026-10-29 23:53:48 +08:00
2026-10-29 23:53:48 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-11-04 08:35:23 +08:00
2026-10-26 20:55:25 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-11-04 11:57:48 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-29 23:53:48 +08:00
2026-11-03 08:46:46 +08:00
2026-10-21 12:17:19 +08:00
2026-10-25 10:10:21 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-11-04 16:24:49 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-18 06:38:51 +08:00
2026-10-29 23:53:48 +08:00
2026-11-04 14:02:58 +08:00
2026-11-04 08:21:15 +08:00
2026-10-23 15:51:02 +08:00
2026-10-29 23:53:48 +08:00
2026-10-26 20:55:25 +08:00
2026-11-04 11:57:48 +08:00
2026-11-04 11:57:48 +08:00
2026-11-04 11:57:48 +08:00
2026-10-21 12:17:19 +08:00
2026-10-29 23:53:48 +08:00
2026-10-29 23:53:48 +08:00
2026-10-23 15:51:02 +08:00
2026-10-21 12:17:19 +08:00
2026-10-05 11:25:20 +08:00
2026-11-04 11:57:48 +08:00
2026-10-25 20:16:16 +08:00
2026-10-25 20:16:16 +08:00
2026-11-04 08:21:15 +08:00
2026-10-26 20:55:25 +08:00
2026-10-29 23:53:48 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-10-21 12:17:19 +08:00
2026-11-04 08:21:15 +08:00
2026-11-04 08:35:23 +08:00
2026-10-21 12:17:19 +08:00