From 4f727beb601ba12b85e40f6c841161bad5d634f6 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Tue, 30 Jun 2026 10:50:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(client/macos):=20=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E5=8D=B3=E6=BF=80=E6=B4=BB=20sysext=20+=20command.sock=20?= =?UTF-8?q?=E6=89=93=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 旧 sysext(on-demand/常驻)会在 app 启动前自动重连,app 走 primeExistingConnection 而非 start() → 永不提交 OSSystemExtensionRequest → bundle 内的新版 sysext 永远装不上, 运行的还是旧版(无 CommandServer)→ command.sock 不存在 → StatsClient 断流(— KB/s + 旧延迟)。 - VpnChannel.register 阶段调 activateOnLaunch():同开发者高版本静默 replace 运行中的旧扩展。 - StatsClient 连接前打点 command.sock 路径与存在性,直接暴露「旧 sysext 没起 CommandServer」。 Co-Authored-By: Claude Opus 4.8 --- client/macos/Runner/StatsClient.swift | 8 ++++++++ client/macos/Runner/VpnChannel.swift | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/client/macos/Runner/StatsClient.swift b/client/macos/Runner/StatsClient.swift index fa4e069..c9ab11a 100644 --- a/client/macos/Runner/StatsClient.swift +++ b/client/macos/Runner/StatsClient.swift @@ -47,6 +47,14 @@ final class StatsClient: NSObject { NSLog("[pangolin/stats] LibboxNewCommandClient returned nil") return } + // 打点:command.sock 由 sysext 的 LibboxCommandServer 在 group 容器内创建。 + // 若此处 sock 不存在 → 跑的是没起 CommandServer 的旧 sysext(版本没换上)。 + if let base = FileManager.default + .containerURL(forSecurityApplicationGroupIdentifier: self.appGroup) { + let sock = base.appendingPathComponent("command.sock").path + let exists = FileManager.default.fileExists(atPath: sock) + NSLog("[pangolin/stats] command.sock=%@ exists=%@", sock, exists ? "YES" : "NO(sysext 未起 CommandServer/旧版)") + } for attempt in 0..<10 { do { try c.connect() diff --git a/client/macos/Runner/VpnChannel.swift b/client/macos/Runner/VpnChannel.swift index 9171a08..e03c34c 100644 --- a/client/macos/Runner/VpnChannel.swift +++ b/client/macos/Runner/VpnChannel.swift @@ -46,6 +46,26 @@ final class VpnChannel: NSObject { .setStreamHandler(StatsStreamHandler(owner: instance)) instance.observeStatus() + // 启动即请求激活 System Extension。关键:隧道可能已被旧 sysext(on-demand/常驻) + // 拉起并自动重连,此时 app 只走 primeExistingConnection、永不调 start() → + // 永不提交激活请求 → 新版 sysext 永远不被装上(旧版一直跑,command.sock 不更新, + // 实时统计断流)。在 register 阶段主动激活一次:同开发者签名的高版本会静默 replace, + // 把运行中的旧扩展换成 bundle 里的新版。 + instance.activateOnLaunch() + } + + /// 启动时主动激活/更新 sysext(幂等):让 bundle 内的新版替换运行中的旧版。 + private func activateOnLaunch() { + Task { + do { + vpnLog("launch: 主动激活 System Extension(确保运行的是 bundle 内最新版)…") + try await activateSystemExtensionIfNeeded() + vpnLog("launch: System Extension 激活/更新完成 ✓") + } catch { + let ns = error as NSError + vpnLog("launch: System Extension 激活失败 ✗ code=\(ns.code) desc=\(ns.localizedDescription)") + } + } } // ── MethodChannel ───────────────────────────────────────────────