merge: task/n17-probe 合入 v2-on-ui
任务 n17(1 个提交)经 task-worktree 回收: - fix(网络): 主动拆会话登记即返——drop 路径不再占用 netTask(登记簿 N-17 收口)
This commit is contained in:
@@ -758,7 +758,9 @@ void net_process_messages(void) {
|
||||
break;
|
||||
}
|
||||
case NET_MSG_DROP_CONN: {
|
||||
/* E-02 收口:应用放弃会话的主动拆除(拆连接、保监听) */
|
||||
/* E-02 收口:应用放弃会话的主动拆除(拆连接、保监听)。监听型
|
||||
* 登记即返(N-17:拆链排渣交 net_listener_tick,本消息不再占用
|
||||
* netTask 数百 ms) */
|
||||
net_sock_t *p_sock = net_get_sock(msg.sockfd);
|
||||
if (p_sock == NULL) {
|
||||
/* 描述符无效 → BADF */
|
||||
@@ -2044,8 +2046,11 @@ static int net_close_locked(net_sock_t *p_sock) {
|
||||
* (PC 内核自动 ACK keepalive,僵尸判不死),单连接监听被永久
|
||||
* 占住;应用又不得 net_close 监听 fd(毁监听)——本函数补上
|
||||
* "拆连接不拆监听"的应用侧形态
|
||||
* 2. 拆除=sock_reset QUARANTINE(TRAP-NET-18 异常释放语义:FIN + 排渣 +
|
||||
* 排空事件(quiescent) + 等 byte0=00H,内置二段 CLOSE 补发)
|
||||
* 2. 芯片侧拆除(TRAP-NET-18 异常释放语义,N-17 收口改异步):监听型 fd
|
||||
* = net_listener_settle(QUARANTINE) + REQ_DROP 登记即返,动作全部交
|
||||
* net_listener_tick(隔离窗内持续排空/关闭正是该机的既有语义);
|
||||
* 非监听 client fd = 同步 sock_reset QUARANTINE(600ms 封顶,原形态)
|
||||
* ——本处理器不得再对监听型做同步等待(netTask 占用窗见 .h 注)
|
||||
* 3. auto_relisten(监听型 fd):收口 CLOSED 后登记重建请求(动作在
|
||||
* net_listener_tick,≤1ms 后执行;芯片已 CLOSED 直接 open 必成,
|
||||
* E4 定案;未成则 30ms 节奏重试 + reconciler 形态④兜底);
|
||||
@@ -2079,8 +2084,20 @@ static int net_drop_conn_locked(net_sock_t *p_sock) {
|
||||
/* 挂起 send 同样先结束(以已发字节数通知;未发部分放弃),再拆芯片会话 */
|
||||
net_send_pending_cancel((int)(p_sock - s_net_socks), NET_ERR_CONNRESET);
|
||||
|
||||
/* 确定性拆除(异常释放 → QUARANTINE 400ms 底,TRAP-NET-18 语义) */
|
||||
if (net_sock_reset_sync(sockfd, CH395F_RESET_QUARANTINE) != 0) {
|
||||
/* 芯片侧拆除按 fd 形态分流(异常释放 = QUARANTINE 语义,TRAP-NET-18)。
|
||||
* 监听型 fd:只登记沉降隔离 + 重建请求,**立即返回**——“排渣/FIN 关闭/
|
||||
* 排空事件/等 byte0=00H/重建”整套动作由 net_listener_tick 以 30ms 节奏执行
|
||||
* (与被动超时释放同一台机器;E16 台架实证该 net 层自建序列 = RST 10/10、
|
||||
* FIN 5/5 的通过版本)。旧形态在本处理器里 net_sock_reset_sync 同步等待,
|
||||
* netTask 被占用 400ms 底/600ms 顶:串行总线整窗停摆、UI/FTP/对时的 API 回
|
||||
* 执顺延、NET 与对时位同窗丢 100ms 抽样 → 800ms 停喂声明 stall,距 IWDG
|
||||
* 最坏超时余量仅 ~0.7s(登记簿 N-17;方向评估与否决论证 → 《网络自愈架构
|
||||
* 设计》§4.6)。返回语义随之明确:返回 = 已登记,芯片未必已拆完。
|
||||
* 非监听 client fd:无监听可保,维持同步确定性排渣(600ms 封顶;全仓
|
||||
* 零生产调用者,形态原样保留防漂移)。 */
|
||||
if (p_sock->auto_relisten != 0U) {
|
||||
net_listener_settle(sockfd, NET_LISTENER_SETTLE_QUARANTINE);
|
||||
} else if (net_sock_reset_sync(sockfd, CH395F_RESET_QUARANTINE) != 0) {
|
||||
DBG_ERROR("sock%d drop_conn: sock_reset not done", sockfd);
|
||||
/* 超时继续收口本层;芯片侧交 reconciler/pump 对账接管 */
|
||||
}
|
||||
@@ -2424,8 +2441,9 @@ int net_close(int sockfd) {
|
||||
* 函数说明:1. 单连接模型下挂起但 TCP 仍活的客户端会永久占住监听(keepalive
|
||||
* 被 PC 内核自动 ACK 判不死,《网络自愈架构设计》§5.2 E13);应用不得
|
||||
* net_close 监听 fd → 本 API 拆连接不拆监听(E-02 收口)
|
||||
* 2. netTask 侧执行 sock_reset QUARANTINE + 监听即时重建(见
|
||||
* net_drop_conn_locked);等待期 netTask 有界占用 ~400-600ms
|
||||
* 2. 监听型 fd:netTask 侧仅登记隔离沉降 + 重建请求即返回(动作在
|
||||
* net_listener_tick,netTask 零占用,登记簿 N-17 收口);非监听 client
|
||||
* fd 仍同步排渣(600ms 封顶)。见 net_drop_conn_locked
|
||||
*/
|
||||
int net_drop_conn(int sockfd) {
|
||||
/* 消息体(按值拷入队列,netTask 改的是其副本) */
|
||||
|
||||
@@ -396,15 +396,22 @@ int net_close(int sockfd);
|
||||
/*
|
||||
* 函数功能:主动拆掉当前 TCP 会话,**保留监听**(E-02 收口)
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* 返回值:0 成功(含幂等:无活动会话),-1 失败
|
||||
* 返回值:0 成功(**监听型 fd 的“成功”= 拆除与重建已登记**,芯片未必已拆完,
|
||||
* 见函数说明 2;含幂等:无活动会话),-1 失败
|
||||
* 限定条件:非 netTask 上下文(经消息队列委托,同其它 net_* API)
|
||||
* 函数说明:1. 适用场景=应用层放弃会话(对时 30s 预算耗尽、协议超时等):
|
||||
* 单连接模型禁止对监听 fd net_close(连监听一起毁,AGENTS 约定),
|
||||
* 而挂起但 TCP 仍活的客户端会永久占住单连接监听(PC 内核自动
|
||||
* ACK keepalive,芯片僵尸判不死——《网络自愈架构设计》§5.2 E13 定案缺口)
|
||||
* 2. 实现=sock_reset QUARANTINE(FIN 关闭 + 排渣 + 排空事件 + 等
|
||||
* byte0=00H,TRAP-NET-18 异常释放语义);auto_relisten fd 随即重监听
|
||||
* (失败交 D10 重试),非 auto_relisten(client fd)收口 CLOSED
|
||||
* 2. 实现(2026-10-25 N-17 起):auto_relisten fd = 登记 QUARANTINE 隔离
|
||||
* 沉降 + REQ_DROP 重建请求,**登记即返**——“FIN 关闭 + 排渣 + 排空
|
||||
* 事件 + 等 byte0=00H”(TRAP-NET-18 异常释放语义)与重建由
|
||||
* net_listener_tick 按 30ms 节奏异步执行,端口恢复窗 ~0.4-1s 与被动
|
||||
* 断连同型;**调用方不得按旧语义假设“返回即芯片已 CLOSED”**——返回
|
||||
* 后 accept/recv 得 WOULDBLOCK 直至重建完成(time_sync 既有轮询天然
|
||||
* 容忍)。旧同步形态曾使 netTask 占用 400-600ms、五任务心跳同窗
|
||||
* 缺席声明 stall(《网络自愈架构设计》§4.6 N-17 记录,勿复活)。
|
||||
* 非 auto_relisten(client fd)无监听可保,仍同步排渣(600ms 封顶)
|
||||
* 3. 幂等:非 ESTABLISHED/CONNECTING 直接返 0,不动监听
|
||||
*/
|
||||
int net_drop_conn(int sockfd);
|
||||
|
||||
+36
-8
@@ -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(服务器侧)
|
||||
|
||||
|
||||
@@ -550,8 +550,10 @@ static void tc_240_drop_conn_branches(void)
|
||||
|
||||
CHECK(g_peers.pending_settle_calls == 1 && g_peers.send_cancel_calls == 1,
|
||||
"TC-NETSOCK-240e both pending tables are ended before dropping the session (with notification)");
|
||||
CHECK(g_fxchip.rst_begin_calls == 1,
|
||||
"TC-NETSOCK-240f teardown uses sock_reset deterministic draining, not close plus blind waiting");
|
||||
CHECK(g_peers.listener_settle_calls == 1 &&
|
||||
g_peers.last_settle_level == (int)NET_LISTENER_SETTLE_QUARANTINE &&
|
||||
g_fxchip.rst_begin_calls == 0,
|
||||
"TC-NETSOCK-240f listener teardown is REGISTERED for the tick machine (QUARANTINE settle + REQ_DROP) - the handler starts no reset machine and never waits (N-17)");
|
||||
CHECK(g_peers.listener_req_calls == 1 &&
|
||||
g_peers.last_req_reason == (int)NET_LISTENER_REQ_DROP,
|
||||
"TC-NETSOCK-240g listener-type fd registers REQ_DROP after the drop (rebuild belongs to the listener layer)");
|
||||
|
||||
@@ -274,7 +274,8 @@ static void tc_320_close_two_paths(void)
|
||||
reset_all();
|
||||
}
|
||||
|
||||
/* TC-NETSOCK-321 drop_conn 用 QUARANTINE(异常释放语义),且不动监听簿记 */
|
||||
/* TC-NETSOCK-321 drop_conn:监听型 = 登记式(settle QUARANTINE + REQ_DROP,
|
||||
* N-17 起 netTask 零占用);非监听 client fd 保留同步排渣;两者都不动监听簿记 */
|
||||
static void tc_321_drop_conn_settle(void)
|
||||
{
|
||||
int fd;
|
||||
@@ -287,8 +288,11 @@ static void tc_321_drop_conn_settle(void)
|
||||
g_fake.cached_open[fd] = CH395F_SOCKET_OPEN;
|
||||
|
||||
CHECK(net_drop_conn(fd) == 0, "TC-NETSOCK-321a drop_conn succeeds");
|
||||
CHECK(g_fxchip.rst_begin_calls == 1 && g_fx.rst_mode[fd] == 1U,
|
||||
"TC-NETSOCK-321b session drop uses QUARANTINE with a 400ms floor (TRAP-NET-18 abnormal release, graded against close)");
|
||||
CHECK(g_peers.listener_settle_calls == 1 && g_peers.last_settle_fd == fd &&
|
||||
g_peers.last_settle_level == (int)NET_LISTENER_SETTLE_QUARANTINE,
|
||||
"TC-NETSOCK-321b listener fd: abnormal-release isolation REGISTERED for the tick machine (TRAP-NET-18 QUARANTINE semantics survive, executed by net_listener_tick)");
|
||||
CHECK(g_fxchip.rst_begin_calls == 0 && g_ns_error_count == 0,
|
||||
"TC-NETSOCK-321b2 N-17: the handler starts no synchronous reset and logs nothing - netTask keeps its ~1ms beat");
|
||||
CHECK(s_net_socks[fd].lost_conn_seen == 0U,
|
||||
"TC-NETSOCK-321c new session start: the missed-event debounce counter is cleared (N-30)");
|
||||
CHECK(s_net_socks[fd].local_port == 2404U && s_net_socks[fd].auto_relisten == 1U &&
|
||||
@@ -300,6 +304,17 @@ static void tc_321_drop_conn_settle(void)
|
||||
CHECK(s_net_socks[fd].readable == 0U && s_net_socks[fd].state == NET_SOCK_STATE_CLOSED,
|
||||
"TC-NETSOCK-321f session bookkeeping closes out: clear readable and move to CLOSED");
|
||||
reset_all();
|
||||
|
||||
/* 非监听 client fd:无监听可保,同步排渣形态原样保留(N-17 只改监听型) */
|
||||
bring_up();
|
||||
fd = mk_established(NET_SOCK_STREAM);
|
||||
g_fake.cached_open[fd] = CH395F_SOCKET_OPEN;
|
||||
CHECK(net_drop_conn(fd) == 0, "TC-NETSOCK-321g client-fd drop still succeeds");
|
||||
CHECK(g_peers.listener_settle_calls == 0 && g_peers.listener_req_calls == 0,
|
||||
"TC-NETSOCK-321h client fd registers no settle and no REQ_DROP: nothing to rebuild");
|
||||
CHECK(g_fxchip.rst_begin_calls == 1 && g_fx.rst_mode[fd] == 1U,
|
||||
"TC-NETSOCK-321i client fd keeps the synchronous QUARANTINE close-out (bounded 600ms, legacy shape)");
|
||||
reset_all();
|
||||
}
|
||||
|
||||
/* TC-NETSOCK-322 close 前必先把挂起结算掉,再动芯片(顺序不可换) */
|
||||
|
||||
@@ -554,16 +554,28 @@ static void tc_460_reset_sync_timeout_bound(void)
|
||||
"TC-NETSOCK-460d the slot is released even on timeout (a chip state must not jam the local fd table)");
|
||||
reset_all();
|
||||
|
||||
/* drop_conn 同一条超时线 */
|
||||
/* N-17:监听型 fd 的 drop 不再走复位等待线——登记即返;即便芯片永不落回
|
||||
* CLOSED 也与本调用无关(排渣与等待归 net_listener_tick 的隔离机) */
|
||||
bring_up();
|
||||
fd = mk_established(NET_SOCK_STREAM);
|
||||
s_net_socks[fd].auto_relisten = 1U;
|
||||
g_fake.cached_open[fd] = CH395F_SOCKET_OPEN;
|
||||
g_fx.rst_keep_open[fd] = 1U;
|
||||
t_before = g_ns_tick;
|
||||
CHECK(net_drop_conn(fd) == 0 && (g_ns_tick - t_before) <= 20U &&
|
||||
g_ns_error_count == 0 && g_peers.listener_settle_calls == 1,
|
||||
"TC-NETSOCK-460e listener drop returns registered and off the beat budget: no 600ms close-out, no [ERR] line, isolation armed (N-17)");
|
||||
reset_all();
|
||||
|
||||
/* 非监听 client fd 保留旧超时线(同步、600ms 封顶、留痕) */
|
||||
bring_up();
|
||||
fd = mk_established(NET_SOCK_STREAM);
|
||||
g_fake.cached_open[fd] = CH395F_SOCKET_OPEN;
|
||||
g_fx.rst_keep_open[fd] = 1U;
|
||||
t_before = g_ns_tick;
|
||||
CHECK(net_drop_conn(fd) == 0 && (g_ns_tick - t_before) <= 700U &&
|
||||
g_ns_error_count >= 1,
|
||||
"TC-NETSOCK-460e drop_conn takes the same bounded close-out and logs it too");
|
||||
"TC-NETSOCK-460f client-fd drop keeps the same bounded close-out as net_close and logs it too");
|
||||
reset_all();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user