Trap23待办3: 异常释放(TIMEOUT/RST)挂起recv以CONNRESET了结, STOR异常结束回450并删除截断文件, 探针加--check-abort
This commit is contained in:
@@ -637,11 +637,11 @@ NET 层 TCP Client(阶段 7)`net_connect()` 返回 0,但 `net_poll()` 报
|
||||
& '.venv\Scripts\python.exe' MDK-ARM\ftp_abort_probe.py --rounds 5 --send 8192 --gap 1 --graceful
|
||||
```
|
||||
|
||||
### 修复方向(待办 N-8)
|
||||
1. **relisten 前让芯片 socket 真正沉降**:确认 `ch395f_get_socket_status == CLOSED` 且清掉该 socket 中断状态后再 listen(现有 relisten 的单次清理在中止场景下不足);
|
||||
2. **新连接的陈旧中断防御**:数据 socket 刚 accept、尚未读到任何数据就收到 DISCONNECT 时判为陈旧中断 → 重新 relisten,而不是当作正常 EOF 结束上传;
|
||||
3. **应用侧兜底**:`receive_file` 区分"正常 EOF"与"连接异常结束",异常时回 5xx(让客户端重试)而非 226,避免误报成功;
|
||||
4. **回归判据**:`ftp_abort_probe.py` 的 `followup` 由 FAIL → **OK(10/10)**,且 `ftp_freeze_probe.py` 的 177 轮对照仍全匹配。
|
||||
### 修复方向(待办 N-8,全部闭环)
|
||||
1. ✅(2026-09-23 一阶段)**relisten 前让芯片 socket 真正沉降**——隔离期:持续排空 RX + 主动 close + 等 `CLOSED/TCP_CLOSED`,隔离满 400ms 才 `open+listen`;
|
||||
2. ✅(2026-09-23/24)**新连接的陈旧中断防御**——陈旧 DISCONNECT 以芯片状态回读甄别(D20:芯片 TCP 仍 ESTABLISHED 判陈旧丢弃)+ 释放残留经两级沉降/隔离(100ms/400ms)后不再投递给下一条连接;
|
||||
3. ✅(2026-09-25)**应用侧兜底**——异常释放(TIMEOUT/RST)的挂起 recv 以 `NET_ERR_CONNRESET` 了结(正常 FIN 仍回 0——协议边界)→ STOR 异常结束回 450 并删除截断文件;
|
||||
4. ✅ **回归判据**——`ftp_abort_probe.py` followup:RST 10/10 + FIN 5/5(一阶段)、8/8 + 5/5 + 5/5(二阶段);`--check-abort` 断言中止 STOR 应答码(RST→450 / FIN→226 边界);177 轮对照当时全匹配,其后各轮正常路径回归全过。
|
||||
|
||||
### 发现时间
|
||||
2026-09-23(可信复现首轮:真实生产路径 FTP 中止/复连场景,由 `MDK-ARM/ftp_abort_probe.py` 自动判定)
|
||||
@@ -701,3 +701,37 @@ NET 层 TCP Client(阶段 7)`net_connect()` 返回 0,但 `net_poll()` 报
|
||||
**结论**:缺陷位于 **fd 复用生命周期**(芯片上一条连接的残留状态投递给下一条连接),不在 FTP 命令逻辑——lftpd 只是把它放大成误报 226。RST/TIMEOUT 半边由一阶段隔离处理,DISCONNECT 半边由本阶段沉降处理,合计覆盖全部"收过数据后关闭"的释放路径。已知残余边界:中止那一笔 STOR 自身仍回报 226(STOR 无长度声明、在途 FIN 与正常完成不可区分)——后续硬化见待办 #3。
|
||||
|
||||
**对应文件**:`Drivers/BSP/NET/net_socket.c`(`handle_disconnect_event` 沉降登记 + `net_relisten_locked` 两级沉降);`MDK-ARM/ftp_abort_probe.py` / `MDK-ARM/bench_diag_abort_gap.py`(边界甄别与回归判据)。
|
||||
|
||||
### 后续硬化(2026-09-25):异常结束回 5xx(待办 #3 闭环)
|
||||
|
||||
**目标**:中止那一笔 STOR 自身不再误报 226——异常结束(连接重置/超时)时回 450 并删除截断文件,把"静默损坏"变成"显式失败"(纵深防御;客户端按协议重试)。
|
||||
|
||||
**实现(3 个工程文件 + 1 个台架脚本)**:
|
||||
1. `net_types.h`:`net_sock_t` 增加释放来源标记 `released_abnormal`(RAM +8B:1B×8 socket,BSS,运行堆零影响);
|
||||
2. `net_socket.c`:`handle_timeout_event`(异常释放/TIMEOUT)置 1;`handle_disconnect_event`(正常释放/DISCONNECT)置 0;`net_socket()`(新 fd)与 `net_relisten_locked` 成功尾(新监听)清零——新连接不得继承上一条连接的释放原因;
|
||||
3. `net_socket.c` `net_pending_tick` 断连了结(③):排空缓冲后,标记为 1 以 `NET_ERR_CONNRESET` 了结(对端未发正常 FIN,不是正常 EOF),标记为 0 仍 EOF(0);
|
||||
4. `lftpd.c` `receive_file`:`err < 0` 时 `unlink` 截断文件(原先残留于盘)并返回错误码 → STOR 处理器回 450;
|
||||
5. `MDK-ARM/ftp_abort_probe.py` 增加 `--check-abort`:RST 中止要求中止 STOR 控制应答 4xx/5xx,优雅 FIN 要求 2xx(协议边界,见下)。
|
||||
|
||||
**协议边界(不可判定,留痕)**:FTP STOR 无长度声明,"在途 FIN 关闭"与"正常完成"**逐字节不可区分**(芯片均报 DISCONNECT、缓冲均排空)→ 优雅中止仍回 226(中止方客户端通常也不等应答);仅 RST/掉链(芯片 TIMEOUT)可识别 → 450。FIN 边界由客户端长度校验(SIZE/RETR 往返)兜底。
|
||||
|
||||
**各消费端负值处理复核**(均按"负值=结束"与 0 同路,行为不变):
|
||||
- lftpd 控制通道 `read_line`:负值 → `line_len != 0` → 会话清理,与 0 同路(控制通道不 close,auto_relisten 恢复);
|
||||
- time_sync(`:8888`):n<0 → break 弃连接,与 0 路径一致;8B 时间包已收齐时仍写 RTC;
|
||||
- UI sink(`:7003`):DONTWAIT 非阻塞,不走 L3 pending,零影响;
|
||||
- 测试套件:产品构建不启用;测试对端干净关闭,无影响。
|
||||
|
||||
**验证(硬化后,2026-09-25 台架)**:
|
||||
|
||||
| 检查项 | 结果 |
|
||||
|---|---|
|
||||
| `ftp_abort_probe --check-abort --rounds 5`(RST) | **5/5**——中止 STOR → **450**(原 226),followup 5/5,控制存活 5/5 |
|
||||
| 设备侧证据 | `sock4 TIMEOUT` → `[ERR][FTP] UPLOAD '/ab0001.bin' FAILED` → 450;followup `UPLOAD '/ab_ok.bin' 4096 bytes OK` |
|
||||
| `--check-abort --graceful --rounds 5`(FIN) | **5/5**——中止 STOR → **226**(边界不变),followup 5/5 |
|
||||
| 正常往返 freeze 4096×4 / 64KB×2 | **4/4 / 2/2**(SHA-256 全 MATCH) |
|
||||
| Trap 22:`:21` 0ms×50 / 100ms×50,`:7003` 300ms×10,`:8888` 0ms×20 | **50/50 / 50/50 / 10/10 / 20/20** |
|
||||
| 非 FTP `:7003` sink 复用(RST×4 / FIN×4,400 帧在途) | **4/4 / 4/4**(ack 2000/2000,LCD 3209/3209,CRC 全过) |
|
||||
| 时间同步 `:8888` 真实收包 | `wall clock updated (epoch=…)` 写 RTC 成功,监听恢复 |
|
||||
| 构建 / 回读 / 启动门禁 / 控制台 / 堆 | 0 错 0 警、`No difference found`、FORBID 0、`CONSOLE dropped 0`、`heap free=8776 min_ever=4816`(不变) |
|
||||
|
||||
**对应文件**:`Drivers/BSP/NET/net_types.h`(`released_abnormal`)、`Drivers/BSP/NET/net_socket.c`(三处置位/清除 + `net_pending_tick` 了结分支)、`Drivers/BSP/NET/lftpd/lftpd.c`(`receive_file` 错误路径 unlink)、`MDK-ARM/ftp_abort_probe.py`(`--check-abort`)。
|
||||
|
||||
Reference in New Issue
Block a user