Skip to content

fix: 状态机停机竞速守门与回调重入会话撕裂修复 + 行为基线(#68 PR-1) - #94

Merged
CSJ608 merged 3 commits into
mainfrom
fix-68-terminal-race-gates
Oct 15, 2026
Merged

CSJ608 merged 3 commits into
mainfrom
fix-68-terminal-race-gates

Conversation

@CSJ608

@CSJ608 CSJ608 commented Oct 15, 2026

Copy link
Copy Markdown
Owner

关闭范围:#68 的 PR-1(行为基线固定 + 排查中发现的两类独立缺陷修复)。不包含内部 Session 对象重构(后续 PR)。

修复的独立缺陷(排查 #68 时实测复现)

1. 终态竞速污染 + 空引用

  • 并发 Dispose 与 Reconnect/连接成功竞速:已通过停机检查、尚未写入 State 的发布线程被抢占,停机写入 Disconnected 后迟到的 Retry/Connected 把终态翻转(State 停在 Retry/Connected)——以 ConcurrentDisposeAndReconnect_TerminalInvariantsHold 高频复现(首迭代即中)。
  • 同竞速中 Retry 派发会对停机回收的 _lifetimeCts 空引用(! 抑制挡不住竞速,NRE 实测复现)。
  • 传输建立与停机竞速:await ConnectAsync/AcceptAsync 返回后无守门,迟到发布会重建会话、socket 无人关闭泄漏到终结器。

2. 回调重入会话撕裂

  • Connected 回调内同步 Reconnect():迟到发布帧的 StartSession 以过期编号/纪元"兜底重建"僵尸会话,其 StopSessionCore 会关掉新会话刚建立的 socket(编号复用 + 会话失活;ConnectedCallback_ReconnectReentry_ConvergesToUsableSession 实测复现,10s 收不到消息)。

修复方式(最小侵入,不重构所有权结构)

  • 发布段原子化:CommunicationStateChanging 拆为发布段(新增 _publishGate 锁内:停机/过期纪元判定 + 编号纪元簿记 + State 写入)与通知段(锁外回调/等待器/派发——回调可安全重入);停机后到达的非终态发布整体丢弃,终态恒为最后可见状态。
  • StartAsync 守门:传输建立后、发布前复查停机(与 Shutdown 末尾关闭块共用 _sessionGate,窗口闭合);_socket 被新连接覆盖时旧值当场释放。
  • StartSession 纪元现行性门控:过期帧(或编号已被归零)放弃创建,由取代者循环完成连接——替代"兜底重建"(兜底正是撕裂根源)。
  • Retry 派发容错:取 _sessionGate 后复查停机;令牌源已回收则放弃派发(容忍取消与回收之间的 ODE)。

行为基线(StateOwnershipBaselineTests,7 例)

迟到发布确定性门控(白盒直发);回调重入收敛性(Connected 内 Reconnect:新会话可用、编号恒非零不复用、合法转移序列;Connected 内 DisposeAsync:终态干净、消息流自然结束);连接成功×停机竞速、并发 Dispose+Reconnect 终态不变量(无泄漏 socket/监听器/孤儿会话,端口可重占)。

DESIGN

新增"状态机与所有权规范"章节:状态转换全表、发布段/通知段规则、资源所有权表、锁清单、允许重入点、已知限制(拆除同步等待持锁 2s、_socket 字段语义——即 #68 后续 PR 的 Session 对象重构方向)。

验证

  • 全套 Release build+test:三 TFM(net8/net10/net48,142/142/134 例)多轮全绿(最终状态 1 轮 + 迭代中共 9+ 轮)。
  • 新测试类单跑 3 轮全绿;全套件含新测试连跑多轮全绿。
  • 备注:调试期曾观察到 RapidServerInitiatedReconnects_PortStaysAcceptable(自带"并行负载下偶发慢收敛"史)在高并发压力下偶发超时;压力测试迭代量收敛(25→10、15→8)后连续多轮稳定。若 CI 偶红该用例,指向已知限制①(StopSessionCore 持锁同步等待),属 PR-2 范围。

@CSJ608
CSJ608 merged commit 989625c into main Oct 15, 2026
5 checks passed
@CSJ608
CSJ608 deleted the fix-68-terminal-race-gates branch October 15, 2026 09:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant