From 15bffce52f0d0f18b9394f8900a0e97f18267ee1 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Mon, 12 Oct 2026 13:34:03 +0800 Subject: [PATCH] =?UTF-8?q?docs(net):=20N-32=20P1=20=E5=8F=B0=E6=9E=B6?= =?UTF-8?q?=E9=AA=8C=E6=94=B6=E8=AE=B0=E5=BD=95=20+=20=E9=AA=8C=E6=94=B6?= =?UTF-8?q?=E8=85=BF=E5=90=A6=E5=AE=9A=E7=BB=93=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit P1 真机验收(@build Code=197096 / 基线 +12B,回读 No difference found): @test PASS;ftp_regression 11/11;Trap23 abort/graceful 各 5/5; :21 0ms×50 与 100ms×50 各 50/50;:8888 0ms×20 20/20; :7003 300ms×10 10/10;设备侧 orphan listener 增量 0。 **否定结论(重要,勿重复踩)**:原计划的"抢先 relisten"验收腿在 真机**外部无法构造**——外部唯一可注入形态(A 发完数据立刻 FIN + 立即 B 抢占)下,P1 版与对照组(撤掉 g_client != g_listen 护栏) **双双 PASS**、设备侧 accept/relisten/disconnect 簿记与 orphan 计数 完全一致 ⇒ 探针无判别力,测不到它声称要测的东西。 机理:真实"抢先"要求 relisten 发生在消费者下一次 recv 之前;对账④ 周期 200ms + 去抖,ui_net_sink 轮询 100ms ⇒ 正常时序消费者总先拿到 EOF。只有拖住 uiTask 才可能出现,而那是设备内部状态。 处置:按 Trap 25「不留未证明的复杂度」删除探针;该场景登记为残余 验证项(需设备内注入点,参照 TEST_LATENCY_PROBE 的编译开关模式)。 故 P1 正确性依据 = ① 代码级论证(边沿→电平、置位/清零完备、两处 relisten 补状态门)② 全量回归矩阵不回归。前瞻场景**未真机证明**, 如实标注,不冒充已验收。 台架观测改用 serial-assistant skill(daemon 独占串口、日志即接口, 设备侧簿记 log --grep 取增量);自建 pyserial 客户端必撞 PermissionError(daemon 独占绑定串口)。 ⚠ SKIP=doc-links:基线预存在问题(另一在途任务未提交文件),非本次引入。 --- .../网络Socket监听生命周期设计说明.md | 49 ++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/docs/子系统设计/网络Socket监听生命周期设计说明.md b/docs/子系统设计/网络Socket监听生命周期设计说明.md index 6327a5f9..9855bad0 100644 --- a/docs/子系统设计/网络Socket监听生命周期设计说明.md +++ b/docs/子系统设计/网络Socket监听生命周期设计说明.md @@ -267,16 +267,53 @@ DONTWAIT 在 LISTENING 下返 `WOULDBLOCK`(`:1890`)→ `ui_net_sink.c:560-56 - [x] `ui_net_sink.c:563` 加 `g_client != g_listen` 护栏;EOF/错误后不再自行 `bind_listen` - [x] 新增 `net_listener_armed(fd)`(LISTENING 或 CLOSED+auto_relisten),替换 `ui_net_sink.c:512` 的 `net_can_accept` 门控(MCU + `net_socket_sim.c` 双端实现) - [x] **超出清单的必要扩展(设计时未预见)**:`net_pending_tick` ③ 断连判据同步改 `CLOSED || session_dead`。不改则 lftpd 的**阻塞** recv 仍会被抢先 relisten 饿死——①要求 ESTABLISHED、③要求 CLOSED,抢先 relisten 后两头落空,只能干等 deadline 超时。判据放宽后,两处 relisten 调用均须补内层 `state == CLOSED` 门:`net_relisten_try` 无状态门,对已 LISTENING 的 fd 再 open+listen 会因 USE 错误走进关闭分支、**关掉正听着新 SYN 的 Socket**(U12 同源事故) -- [ ] 验收:新增"抢先 relisten"腿(连上 :7003 → 拖住 uiTask → 断连 → 断言 sink 仍得 EOF **且下一个客户端被服务**)+ 全量回归矩阵(§7.1 那一套) -- [ ] `@test` PASS → 回读校验 → 停下等提交指令 +- [x] 全量回归矩阵(§7.1 那一套)—— 2026-10-12 真机全绿,见下「P1 台架验收记录」 +- [!] 「抢先 relisten」腿 —— **外部注入不可构造,已放弃**:见下「验收腿的否定结论」 +- [x] `@test` PASS → 回读校验(`No difference found`) + +**P1 台架验收记录(2026-10-12,`@build` Code=197096 / 基线 197084,+12 B)** + +| 腿 | 结果 | 说明 | +|---|---|---| +| `@test` 启动闭环 | **PASS** | 启动锚点齐、无 `[ERR]`、reset cause ×1、7.2 s 到 net ready | +| `ftp_regression` | **11/11** | 含 STOR 32KB —— 「发完即 FIN」链路,`session_dead` 直接作用面 | +| Trap 23 `--check-abort`(RST) | **5/5** | 450 + 5xx 正确回报,无误报 226 | +| Trap 23 `--graceful`(FIN) | **5/5** | 226 正常 | +| `:21` 快速复连 0 ms ×50 | **50/50** | Trap 22 基线不回归 | +| `:21` 快速复连 100 ms ×50 | **50/50** | 同上 | +| `:8888` 0 ms ×20 | **20/20** | 对时服务不回归 | +| `:7003` 300 ms ×10 | **10/10** | B10 原始失败场景(修复前 0/10) | +| 设备侧孤儿对账 `orphan listener` | **0 次** | 探针时段经 serial-assistant `clear` 划界后统计 | + +> 台架观测用 **`serial-assistant` skill**(daemon 独占串口、日志即接口)—— +> 设备侧簿记(`standalone accept` / `auto-relisten ok` / `DISCONNECTED, releasing` / +> `orphan listener`)直接 `log --grep` 取增量,无需自建串口客户端。 +> ⚠ 自建 pyserial 客户端会撞 `PermissionError(拒绝访问)`:daemon 独占绑定串口。 + +**验收腿的否定结论(重要,勿再重复踩)**:设计文档原计划的新增腿是 +「连上 :7003 → 拖住 uiTask 使 relisten 先发生 → 断连 → 断言 sink 仍得 EOF」。 +2026-10-12 实现后发现**真机外部无法构造**,且据此写的探针**无判别力**: + +- 外部唯一可注入的是「A 发完数据立刻 FIN + 立即 B 抢占」。实测该形态下 + **P1 版与对照组(撤掉 `g_client != g_listen` 护栏)双双 PASS**,设备侧 + `accept/relisten/disconnect` 簿记与 `orphan` 计数完全一致 → 探针测不到它声称要测的东西。 +- 机理:真实「抢先」要求 relisten 发生在**消费者下一次 recv 之前**;而对账④ 周期 + 200 ms + 去抖(`NET_RECONCILE_STABLE_N`),`ui_net_sink` 轮询 100 ms —— + 正常时序下消费者总是先 recv 到 EOF,对账抢不到。**只有 uiTask 被拖住**才可能出现, + 而那是设备内部状态。 +- 处置:按 Trap 25「不留未证明的复杂度」**删除该探针**;该场景登记为**残余验证项**, + 需设备内注入点(参照 `TEST_LATENCY_PROBE` 的编译开关模式)才能在真机复现。 +- 因此 P1 的**正确性依据**是:① 代码级论证(判据由边沿改电平、置位/清零完备、 + 两处 relisten 补状态门);② 上表全量回归矩阵**不回归**;③ 不变量 I 的结构性论证。 + 「抢先」的前瞻场景**未被真机证明**,如实标注,不冒充已验收。 **P1 落成状态(2026-10-12)**:代码已实现、`@build` 0 错 0 警(`Code=197096`,较基线 +12 B)、 `mem-numbers` 快照已 `--write` 刷新、除下述基线问题外静态门禁全绿。 ⚠ **已知基线问题(非本改动引入)**:`doc-links` 在**任何从当前 `v2-on-ui` 切出的工作树**上都会报 -2 处失效引用——`RAM使用分析与优化方案.md:277/:585` → `scripts/ram_baseline.tsv`、 -`docs/内存管理/RAM预算台账.md`。这两个文件属另一在途任务、尚未提交,主工作树磁盘上有故主线 -门禁呈绿(见 `docs/环境与部署/并行任务工作树方案.md` §10.2)。待该任务合入后自动消解, -**不应**由本分支代为提交他人半成品。 +2 处失效引用——`RAM使用分析与优化方案.md` 引用了两个**尚未提交**的文件(RAM 基线 `.tsv` 与 +RAM 预算台账 `.md`,属另一在途任务)。这两个文件在主工作树磁盘上存在故主线门禁呈绿, +工作树里没有故必报红(机理见 `docs/环境与部署/并行任务工作树方案.md` §10.2)。 +待该任务合入后自动消解,**不应**由本分支代为提交他人半成品。 **P2(单一所有者)** - [ ] 新增 `net_listener_pump()`,与 `net_reconcile_tick` 同节拍,成为**唯一**调 `net_relisten_try` 的监听重建入口