From 3ed2341355e32b4a04afd4693e04687751f2e86d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Wed, 22 Apr 2026 01:53:35 +0800 Subject: [PATCH] Improve oom-killer --- HelperService/RootHelperService.swift | 5 +++++ Library/Network/ExtensionProfile.swift | 29 ++++++++++++++++++++++++- Library/Network/ExtensionProvider.swift | 1 + Library/Network/RootHelperXPC.swift | 7 ++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/HelperService/RootHelperService.swift b/HelperService/RootHelperService.swift index e6c7265..05ff785 100644 --- a/HelperService/RootHelperService.swift +++ b/HelperService/RootHelperService.swift @@ -253,6 +253,11 @@ extension RootHelperService: RootHelperProtocol { reply(result, nil) } + func promoteOOMDraft(reply: @escaping (NSError?) -> Void) { + LibboxPromoteOOMDraftAt(WorkingDirectoryManager.extensionWorkingDirectoryPath) + reply(nil) + } + func triggerGoCrash(reply: @escaping (NSError?) -> Void) { reply(nil) LibboxTriggerGoPanic() diff --git a/Library/Network/ExtensionProfile.swift b/Library/Network/ExtensionProfile.swift index c09f66c..986fc7a 100644 --- a/Library/Network/ExtensionProfile.swift +++ b/Library/Network/ExtensionProfile.swift @@ -62,6 +62,9 @@ public class ExtensionProfile: ObservableObject { self.connection = connection self.status = connection.status self.connectedDate = connection.connectedDate + if connection.status == .disconnected { + Self.schedulePromoteOOMDraft() + } #if os(iOS) if #available(iOS 16.0, *) { if connection.status == .connected || connection.status == .disconnected { @@ -73,6 +76,26 @@ public class ExtensionProfile: ObservableObject { } } + private static func schedulePromoteOOMDraft() { + Task.detached { + try? await Task.sleep(nanoseconds: 2 * NSEC_PER_SEC) + #if os(macOS) + if Variant.useSystemExtension { + guard HelperServiceManager.rootHelperStatus == .enabled else { + return + } + do { + try RootHelperClient.shared.promoteOOMDraft() + } catch { + logger.warning("promote OOM draft: \(error.localizedDescription)") + } + return + } + #endif + LibboxPromoteOOMDraft() + } + } + #if os(iOS) @available(iOS 16.0, *) private static func signalFileProviderChanges() { @@ -291,7 +314,11 @@ public class ExtensionProfile: ObservableObject { if managers.isEmpty { return nil } - return ExtensionProfile(managers[0]) + let profile = ExtensionProfile(managers[0]) + if profile.status == .disconnected { + schedulePromoteOOMDraft() + } + return profile } public static func install() async throws { diff --git a/Library/Network/ExtensionProvider.swift b/Library/Network/ExtensionProvider.swift index 0b1882a..38c1ff9 100644 --- a/Library/Network/ExtensionProvider.swift +++ b/Library/Network/ExtensionProvider.swift @@ -176,6 +176,7 @@ open class ExtensionProvider: NEPacketTunnelProvider { if let setupError { throw ExtensionStartupError("(packet-tunnel) error: setup service: \(setupError.localizedDescription)") } + LibboxPromoteOOMDraft() var error: NSError? commandServer = LibboxNewCommandServer(platformInterface, platformInterface, &error) diff --git a/Library/Network/RootHelperXPC.swift b/Library/Network/RootHelperXPC.swift index 43eb7fd..348d7ab 100644 --- a/Library/Network/RootHelperXPC.swift +++ b/Library/Network/RootHelperXPC.swift @@ -193,6 +193,7 @@ func registerMyInterface(name: String, reply: @escaping (NSError?) -> Void) func collectAllCrashArtifacts(reply: @escaping (CrashArtifactsResult?, NSError?) -> Void) func collectOOMReportArtifacts(reply: @escaping (OOMReportArtifactsResult?, NSError?) -> Void) + func promoteOOMDraft(reply: @escaping (NSError?) -> Void) func triggerGoCrash(reply: @escaping (NSError?) -> Void) func triggerNativeCrash(reply: @escaping (NSError?) -> Void) } @@ -441,6 +442,12 @@ } } + public func promoteOOMDraft() throws { + try performXPCCallVoid("promoteOOMDraft") { proxy, reply in + proxy.promoteOOMDraft(reply: reply) + } + } + public func triggerGoCrash() throws { try performXPCCallVoid("triggerGoCrash") { proxy, reply in proxy.triggerGoCrash(reply: reply)