Tools View & Crash Report & OOM Report

This commit is contained in:
世界
2026-04-23 08:12:52 +08:00
parent 73180f0230
commit b48f4ad97f
46 changed files with 4279 additions and 533 deletions
+123
View File
@@ -27,6 +27,7 @@ class RootHelperService: NSObject {
private var pathMonitor: NWPathMonitor?
private var pendingNATFlush: DispatchWorkItem?
private var tunInterfaceName: String?
var pendingCrashLogs: [CrashLogFileResult] = []
func start() {
listener = NSXPCListener(machServiceName: AppConfiguration.rootHelperMachService)
@@ -142,6 +143,128 @@ extension RootHelperService: RootHelperProtocol {
reply(nil)
}
static func readCrashLogFiles() -> [CrashLogFileResult] {
var results: [CrashLogFileResult] = []
let crashLogSearchPaths: [(directory: String, fileNames: [String])] = [
(WorkingDirectoryManager.extensionWorkingDirectoryPath, [
"CrashReport-NetworkExtension.log",
"CrashReport-NetworkExtension.log.old",
]),
(WorkingDirectoryManager.helperWorkingDirectoryPath, [
"CrashReport-RootHelper.log",
"CrashReport-RootHelper.log.old",
]),
(WorkingDirectoryManager.extensionBasePath, [
"configuration.json",
]),
(WorkingDirectoryManager.helperBasePath, [
"configuration.json",
]),
]
for searchPath in crashLogSearchPaths {
for fileName in searchPath.fileNames {
let filePath = (searchPath.directory as NSString).appendingPathComponent(fileName)
guard FileManager.default.fileExists(atPath: filePath),
let content = try? String(contentsOfFile: filePath, encoding: .utf8),
!content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
else {
continue
}
let attrs = try? FileManager.default.attributesOfItem(atPath: filePath)
let modificationDate = (attrs?[.modificationDate] as? Date) ?? Date()
results.append(CrashLogFileResult(
fileName: fileName,
content: content,
modificationDate: modificationDate
))
try? FileManager.default.removeItem(atPath: filePath)
}
}
return results
}
func collectAllCrashArtifacts(reply: @escaping (CrashArtifactsResult?, NSError?) -> Void) {
let result = CrashArtifactsResult()
var crashLogs = pendingCrashLogs
pendingCrashLogs.removeAll()
crashLogs.append(contentsOf: Self.readCrashLogFiles())
result.crashLogs = crashLogs
result.helperNativeCrashData = NativeCrashReporter.loadAndPurgePendingCrashReportData()
let extensionReportURL = CrashReportArchive.pendingNativeCrashReportURL(
basePath: URL(fileURLWithPath: WorkingDirectoryManager.extensionNativeCrashBasePath, isDirectory: true),
bundleIdentifier: AppConfiguration.systemExtensionBundleID
)
if let data = try? Data(contentsOf: extensionReportURL), !data.isEmpty {
result.extensionNativeCrashData = data
try? FileManager.default.removeItem(at: extensionReportURL)
}
reply(result, nil)
}
func collectOOMReportArtifacts(reply: @escaping (OOMReportArtifactsResult?, NSError?) -> Void) {
let result = OOMReportArtifactsResult()
let oomReportsPath = WorkingDirectoryManager.extensionOOMReportsPath
let fm = FileManager.default
guard fm.fileExists(atPath: oomReportsPath),
let entries = try? fm.contentsOfDirectory(atPath: oomReportsPath)
else {
reply(result, nil)
return
}
for entry in entries {
let dirPath = (oomReportsPath as NSString).appendingPathComponent(entry)
var isDir: ObjCBool = false
guard fm.fileExists(atPath: dirPath, isDirectory: &isDir), isDir.boolValue else {
continue
}
guard let fileNames = try? fm.contentsOfDirectory(atPath: dirPath) else {
continue
}
var files: [OOMReportFileResult] = []
for fileName in fileNames {
let filePath = (dirPath as NSString).appendingPathComponent(fileName)
guard let data = fm.contents(atPath: filePath) else {
continue
}
files.append(OOMReportFileResult(name: fileName, data: data))
}
if !files.isEmpty {
result.reports.append(OOMReportDirectoryResult(directoryName: entry, files: files))
}
try? fm.removeItem(atPath: dirPath)
}
reply(result, nil)
}
func triggerGoCrash(reply: @escaping (NSError?) -> Void) {
reply(nil)
LibboxTriggerGoPanic()
}
func triggerNativeCrash(reply: @escaping (NSError?) -> Void) {
reply(nil)
DispatchQueue.global().asyncAfter(deadline: .now() + .milliseconds(200)) {
fatalError("debug native crash")
}
}
func closeNeighborMonitor(reply: @escaping (NSError?) -> Void) {
logger.info("closeNeighborMonitor")
closeNeighborMonitorInternal()
+36 -4
View File
@@ -2,12 +2,44 @@ import Foundation
import Library
enum WorkingDirectoryManager {
private static var workingDirectoryPath: String {
"/var/root/Library/Containers/\(AppConfiguration.systemExtensionBundleID)/Data/Working"
static var extensionBasePath: String {
"/var/root/Library/Containers/\(AppConfiguration.systemExtensionBundleID)/Data"
}
static var extensionWorkingDirectoryPath: String {
(extensionBasePath as NSString).appendingPathComponent("Working")
}
static var tempDirectoryPath: String {
"/var/root/Library/Containers/\(AppConfiguration.systemExtensionBundleID)/Data/Temp"
}
static var helperBasePath: String {
"/var/root/Library/Containers/\(AppConfiguration.rootHelperBundleID)/Data"
}
static var helperWorkingDirectoryPath: String {
(helperBasePath as NSString).appendingPathComponent("Working")
}
static var helperTempDirectoryPath: String {
(helperBasePath as NSString).appendingPathComponent("Temp")
}
static var helperNativeCrashBasePath: String {
(helperBasePath as NSString).appendingPathComponent("NativeCrash")
}
static var extensionNativeCrashBasePath: String {
"/var/root/Library/Containers/\(AppConfiguration.systemExtensionBundleID)/Data/NativeCrash"
}
static var extensionOOMReportsPath: String {
(extensionWorkingDirectoryPath as NSString).appendingPathComponent("oom_reports")
}
static func getSize() -> Int64 {
let path = workingDirectoryPath
let path = extensionWorkingDirectoryPath
guard FileManager.default.fileExists(atPath: path) else {
return 0
}
@@ -28,7 +60,7 @@ enum WorkingDirectoryManager {
}
static func clean() throws {
let path = workingDirectoryPath
let path = extensionWorkingDirectoryPath
guard FileManager.default.fileExists(atPath: path) else {
return
}
+17
View File
@@ -1,5 +1,22 @@
import Foundation
import Libbox
import Library
NativeCrashReporter.installForCurrentProcess(
basePath: URL(fileURLWithPath: WorkingDirectoryManager.helperNativeCrashBasePath, isDirectory: true)
)
let pendingCrashLogs = RootHelperService.readCrashLogFiles()
let setupOptions = LibboxSetupOptions()
setupOptions.basePath = WorkingDirectoryManager.helperBasePath
setupOptions.workingPath = WorkingDirectoryManager.helperWorkingDirectoryPath
setupOptions.tempPath = WorkingDirectoryManager.helperTempDirectoryPath
setupOptions.crashReportSource = "RootHelper"
var setupError: NSError?
LibboxSetup(setupOptions, &setupError)
let service = RootHelperService()
service.pendingCrashLogs = pendingCrashLogs
service.start()
dispatchMain()