Leadaxe 记录 LxBox 空闲后停止卡住,内核原因仍待抓栈确认
Leadaxe 在 sing-box-lx #50 中记录:一份 Android LxBox 代理模式(无 TUN)、使用 WireGuard/AmneziaWG/WARP 端点的现场报告称,设备空闲约 6 小时后停止服务会一直停在 Stopping;目前没有 logcat 或 goroutine dump。作者说明 LxBox 端已有强停绕过处理,但内核关闭仍会阻塞。仅按代码阅读,他怀疑端点关闭的锁或等待、以及 detour 连接的 ReadFrom 未被唤醒,并提出关闭期限、带期限获取锁和主动关闭连接等候选方案。他明确要求先等 doStop 看门狗抓到设备栈再按证据修复;上述原因及改法尚未确认。
作者原文@LeadaxeSymptom
LxBox on Android, proxy mode (no tun), config with WireGuard/AmneziaWG/WARP endpoints. After ~6 h of device idle, stopping the service never completes:
closeCommandServerAtomic→CommandServer.closeService()does not return, status staysStoppinguntil the process is killed. One field report, no logcat or goroutine dump.LxBox already works around it on its side (LxBox task 663: force-stop reaches the service even after its receiver is gone; a follow-up adds timeouts and a stuck-step watchdog with a goroutine dump to
doStop). The core itself still blocks.Hypothesis (code reading only, not confirmed)
started_service.go:341 instance.Close→box.go:698 scope.Close→adapter/endpoint/manager_close_lx.go:51 group.Run(no deadline) → WireGuardEndpoint.Closeblocks on one of:
protocol/wireguard/endpoint.go:513bindAccess.Locktransport/wireguard/endpoint.go:463pauseOpAccess.Lockwireguard-go/device.go:789stopping.Waitheld by a receive worker parked in
client_bind.go:180 ReadFromon a detour conn thatClose()does not wake (same class as SPEC 072; its "deliberately not done" assumed bounded dial, butReadFromon an established detour conn is not covered by that deadline). Overnight Doze pause/wake cycles and network changes (route/network.go:468) make this likelier. SinceCloseServiceclearss.instancebeforeClose(started_service.go:338), later wake/resetNetwork calls from the platform become no-ops, so it never recovers.Secondary:
CloseServicewaiting onlifecycleAccess(started_service.go:331) held by a stuckStartOrReloadService(:252) whose old-instanceCloseis the same hang.To do once a device dump arrives
Fix by evidence, not by hypothesis. Wait for a goroutine dump from LxBox's
doStopwatchdog (stuck at closeCommandServer+PProfClient.goroutineDump). Expected stacks if the hypothesis holds:closeBindLocked → WaitGroup.Waitwith a worker inClientBind.receive/ReadFrom, orEndpoint.Close → Mutex.Lockwith the holder inupdateBind/resumeOnDial.Candidate fixes:
closeEndpoints: run with a context deadline instead of an unboundedgroup.Run;Endpoint.Close:TryLockonbindAccesswith a deadline, and close the detour conn soReadFromreturns;CloseService: bounded wait onlifecycleAccess.