merge: task/n17-probe 合入 v2-on-ui

任务 n17(1 个提交)经 task-worktree 回收:
- fix(网络): 主动拆会话登记即返——drop 路径不再占用 netTask(登记簿 N-17 收口)
This commit is contained in:
2026-10-25 10:32:25 +08:00
6 changed files with 108 additions and 26 deletions
+36 -8
View File
@@ -422,17 +422,45 @@ CLOSED → 由形态④ 接手。关键在两条快路径的判据(`net_pendin
必须 `net_select` 超时或 `net_recv_to` 显式预算。
- 上层 32 轮盲收(`ui_net_sink` / `iec104_serv`)保留现状(E6 裁决,§4.8)。
### 4.6 `net_drop_conn`——应用主动拆会话保监听(E-02 收口)
### 4.6 `net_drop_conn`——应用主动拆会话保监听(E-02 收口;N-17 异步收口 2026-10-25)
- 语义:`net_pending_settle_close` 先结束挂起 recv(回传结果 + 唤醒调用方)→
`net_sock_reset_sync(QUARANTINE)` → 本层收口 CLOSED(不清 fd)→ `auto_relisten` 即时登记
重建请求(`net_listener_tick` 执行;失败交 D10 + 形态④)。
- 语义(**返回值 = 拆除与重建已登记**,不代表芯片已拆完):`net_pending_settle_close`
先结束挂起 recv(回传结果 + 唤醒调用方)→ 监听型(`auto_relisten`)fd:
`net_listener_settle(QUARANTINE)` + `net_listener_request(REQ_DROP)` 登记即返,
芯片拆除(FIN 关闭 + 排渣 + 排空事件 + 等 byte0=00H)与重建由 `net_listener_tick`
按 30ms 节奏执行(与被动超时/断连释放同一台机器),失败交 D10 + 形态④;
非监听 client fd 无监听可保,仍同步 `net_sock_reset_sync`(600ms 封顶)。
端口恢复窗 ~0.4~1s,与被动断连恢复窗(E1 发现 A)同型。
- **为什么监听型不得同步等待(N-17 定位,论证随结论一并留档)**:旧形态在
`NET_MSG_DROP_CONN` 处理器内同步跑 `net_sock_reset_sync(QUARANTINE)`(2ms 节奏、
400ms 底/600ms 顶,自家注释原记「等待期 netTask 有界占用 ~400-600ms」),netTask
的 1ms 主循环冻结在同一迭代内:NET 位心跳停摆 + 串行总线整窗停摆(UI 推流/FTP/
104 在途消息回执顺延、调用方在其分片/无限等待中不见回执)+ 对时调用方自己睡在
`net_wait_result` 等回执、期间无分片心跳——五位同窗缺席 → 连续 8 个 100ms 抽样
停喂 → 声明 `[WD] task stall`(V5 时代 req=0x37,缺席位恰为 NET/FTP/UI/对时,
快照只剩 bit0,即日志中的 `mask=0x00000001`),缺口 800ms~1s,距 IWDG 最坏超时
1701ms 余量仅 ~0.7s;同场隔离负载(纯 FTP 120s)0 次——因为被动拆链走的本就是
异步沉降机(D10「重建必须非阻塞」条令),只有主动 drop 一条路径留在同步原语里。
- **评估否决的方向——「缩短重建重试(5×2s)」**:该退避链在
`time_sync_open_listener()` 的 bind/listen 失败路径,全程走
`time_sync_delay_fed()` ≤50ms 分片喂心跳,且**不在 drop→拆链→重监听的心跳缺口
链上**;缩短它不消除本缺口,反而加大对芯片沉降窗的撞车风险(TRAP-NET-09:关闭
后需沉降才能重开),故不采。
- **竞态与信源核对**:① 主路径置 CLOSED 后迟到的 DISCONNECT/TIMEOUT 事件被
`net_events` 的状态门拦截(只认活会话态),不会把刚登记的 QUARANTINE 降级为
GRACEFUL;② 零新增读清点——隔离窗内两处本 Socket 读清仍在 `net_listener_tick`
原位置(§4.10.2),全局寄存器唯一读者仍是 `net_poll`;③ 生产调用者全仓仅
`time_sync.c`(不消费返回值,accept 轮询天然容忍 WOULDBLOCK 窗)。
- **幂等**(非 ESTABLISHED/CONNECTING 直接返 0);**EOF 路径不得调**
(`auto_relisten` 已接管,再调属重复拆)。
- 芯片物理边界(E-02 台架):`close` **无 RST 语义**——对端配合(收到 FIN 后其内核
close):`TIME_WAIT` ~150ms → 形态④ relisten(恢复全程 ~500ms);对端内核存活但
不 close:芯片停 `FIN_WAIT_2` 长尾,**监听恢复受限于对端 close**,兜底 = 芯片
TIMEOUT/KeepAlive 拆僵尸 30~90s(E13)——不是应用可加速的路径。
- 芯片物理边界(E-02 台架,异步收口逐字不变——只移动「等待发生在哪」):
`close` **无 RST 语义**——对端配合(收到 FIN 后其内核 close):`TIME_WAIT` ~150ms
→ 形态④ relisten(恢复全程 ~500ms);对端内核存活但不 close:芯片停
`FIN_WAIT_2` 长尾,**监听恢复受限于对端 close**,兜底 = 芯片 TIMEOUT/KeepAlive 拆
僵尸 30~90s(E13)——不是应用可加速的路径。
- 回归锚点:`TC-NETSOCK-240efg / 321 全组 / 460ef`(登记式、netTask 零占用、
client fd 旧形态保留);台架判据 = V5 复跑(e02_probe + FTP ≥30min)零 stall,
见 `docs/测试说明/实机测试实施指南.md` §4。
### 4.7 KeepAlive(服务器侧)