Tools View & Crash Report & OOM Report
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user