Leadaxe 说明 sing-box-lx 关闭预处理恢复与卡住诊断
Leadaxe 在 sing-box-lx #50 的后续中说明,代码阅读排除了 pause manager 和有界拨号阻塞停止的假设;等待最终落在已建立 detour 连接的收发工作线程,具体连接仍需设备转储确认。原先依赖设备暂停事件的 WireGuard 关闭预处理自 lx.37 起失效,现改为在端点拆除前释放 WG/AWG 套接字。新增看门狗在端点关闭或整个 Box.Close 超过 20 秒时,以 Warn 分块写出一次完整 goroutine 转储和未返回端点标签,但继续等待,不中断关闭。评论当时称随下一版本提供;随后发布的 v1.14.3-lx.23 已列入这两项。
作者原文@LeadaxeUpdate after reading the close path (2026-10-23).
Ruled out by code.
daemon.Instance.Closecancels the core context beforebox.Close, so the pause manager'sWaitActiveand the boundedClientBinddials cannot hold the stop. All three mutexes above (bindAccess,pauseOpAccess,resumeMu) end in wireguard-go'sstopping.Wait, i.e. in a receive/send worker that does not leaveReadFrom/Writeon an established detour conn. Which conn, only a dump can tell.Two changes land in the next release:
- the SPEC 030 shutdown pre-pass is restored. It had been silently dead since lx.37: upstream 6364d9a5f dropped the WireGuard reaction to the device-pause event the pre-pass relied on, so every
device.Closewas waiting out its own receive worker. Every WG/AWG socket is now released up front, before the endpoint teardown (351e04f4b);- a close watchdog: if
closeEndpointsor the wholeBox.Closeruns past 20 s, the core writes one full goroutine dump to its own log at Warn, split into ≤3 KiB chunks so logcat does not truncate it, with the tags of the endpoints that have not returned fromCloseyet, and keeps waiting. The close is never interrupted (35db11609, SPEC 030 §8).With that build a hung stop needs no pprof: please attach the core log for the minute of the hang, all
goroutine dump [i/M]records plus thenot returned yet: [...]line.