• v0.4.2 3e7df0f4d8

    fix: 修复连接状态下切换配置后断开重连导致异常的问题
    Release / build-macos (push) Canceled after 0s
    Release / build-windows (push) Canceled after 0s
    Release / release (push) Canceled after 0s

    kevin released this 2026-07-08 08:57:50 -04:00 | 19 commits to main since this release

    问题现象:连接中切换配置 -> 断开 -> 连接,会出现连接后瞬间断开、
    长时间无法重连。而先断开再切换配置则正常。

    根因分析(三个层面的资源泄漏叠加):

    1. pumpPackets 死锁 (session.go)
      Disconnect() 只关闭 WebSocket transport,不关闭 TUN 设备。
      TUN->WS goroutine 阻塞在 dev.Read(),pumpPackets 的 wg.Wait()
      永远不返回,cleanup()(关闭 TUN/删路由)无法执行,导致
      TUN 设备和路由泄漏。

    2. 僵尸 eventLoop + 僵尸 IPC 连接 (view.go)
      onDisconnect 不清空 ipcClient、不关闭 IPC 连接,旧 eventLoop
      持续运行接收广播事件。eventLoop 正常事件处理无身份校验,
      旧 session 的 disconnected 广播会覆盖新 session 的 connected 状态。

    3. stopSession 不等待 goroutine 退出 (daemon.go)
      d.session = nil 在 goroutine 仍在运行时即设置,新旧 session
      并发执行导致 TUN/路由冲突。无 mutex 保护并发访问。

    修复内容(10 项,3 个文件):

    session.go:

    • Disconnect() 新增 dev.Close() 解除 pumpPackets 死锁
    • 新增 done channel,Disconnect() 阻塞等待 run goroutine 完全退出
    • run() deferred setState 跳过用户主动断开时的冗余广播
    • run() 顶部 ctx.Err() 检查后补 cleanup()

    daemon.go:

    • 新增 sync.Mutex 保护 session/cancel 并发访问
    • 拆分 stopSession/stopSessionLocked 避免死锁

    view.go:

    • onDisconnect 置 ipcClient=nil + client.Close() 终止僵尸 eventLoop
    • eventLoop 三个事件分支均加 if current == client 身份校验
    • onConnect 覆盖前清理旧 IPC client
    • setConnButtons 连接时禁用配置下拉框
    Downloads