【发布时间】:2019-05-11 12:30:34
【问题描述】:
需要帮助以了解崩溃的真正原因。我已经制作了应该 24/7 全天候运行的应用程序。它从设备读取并准备一些数据,并创建一个 Web 服务器以将数据发送到探测器。 崩溃是在不同的时间后发生的,所以我无法在模拟器中真正重现它。
这是最后一个崩溃文件的详细信息:
自启动以来的唤醒时间:110000 秒
系统完整性保护:启用
崩溃的线程:37 调度队列:com.apple.root.default-qos
异常类型:EXC_CRASH (SIGABRT)
异常代码:0x0000000000000000, 0x0000000000000000
异常说明:EXC_CORPSE_NOTIFY
已达到调度线程软限制:64(同步操作中阻塞的调度线程过多)
应用特定信息: abort() 调用
*** 对象 0x247032000 的错误:未分配被释放的指针
线程 37 的详细信息:
线程 37 崩溃::调度队列:com.apple.root.default-qos
0 libsystem_c.dylib 0x00007fff8dab3298 usleep$NOCANCEL + 0
1 libsystem_c.dylib 0x00007fff8dae16e9 中止 + 139
2 libsystem_malloc.dylib 0x00007fff965fe041 免费 + 425
3 libswiftCore.dylib 0x0000000106fed219 $Ss19_SwiftStringStorageCfD + 9
4 libswiftCore.dylib 0x0000000106ffba00 _swift_release_dealloc + 16
...
46 org.cocoapods.GCDWebServer 0x0000000106c67316 -[GCDWebServerConnection(Subclassing) processRequest:completion:] + 128
47 org.cocoapods.GCDWebServer 0x0000000106c6392e -[GCDWebServerConnection _startProcessingRequest] + 146
48 org.cocoapods.GCDWebServer 0x0000000106c64e13 __45-[GCDWebServerConnection _readRequestHeaders]_block_invoke + 1781
49 org.cocoapods.GCDWebServer 0x0000000106c65935 __64-[GCDWebServerConnection(Read) readHeaders:withCompletionBlock:]_block_invoke + 290
50 org.cocoapods.GCDWebServer 0x0000000106c65613 __68-[GCDWebServerConnection(Read) readData:withLength:completionBlock:]_block_invoke + 307
51 libdispatch.dylib 0x00007fff8e73c7a8 __dispatch_read_block_invoke_252 + 39
52 libdispatch.dylib 0x00007fff8e72a93d _dispatch_call_block_and_release + 12
53 libdispatch.dylib 0x00007fff8e71f40b _dispatch_client_callout + 8
54 libdispatch.dylib 0x00007fff8e72329b _dispatch_root_queue_drain + 1890
55 libdispatch.dylib 0x00007fff8e722b00 _dispatch_worker_thread3 + 91
56 libsystem_pthread.dylib 0x00007fff8ea934de _pthread_wqthread + 1129
57 libsystem_pthread.dylib 0x00007fff8ea91341 start_wqthread + 13
代码:
这是处理 Web 服务器 (GCDWebServer) 的单音代码。它根据http查询中的id读取存储在内存中的数据
private let queue = DispatchQueue(label: "gcdwebserver_queue")
private func setupServer(){
webServer.delegate = self
webServer.addDefaultHandler(forMethod: "GET", request: GCDWebServerRequest.self) { (req, completion) in
if let resp = self.response(for: req) {
return completion(resp)
}
}
queue.async {
self.webServer.start(withPort: 8521, bonjourName: "GCD Web Server")
}
}
这是一个调用 modbus(C Modbus 库)连接(每 30 秒)到设备列表并读取数据的单例代码:
private let modbusQueue = DispatchQueue(label: "modbus_queue")
private func initiateTimer() {
polling()
timer?.invalidate()
if #available(OSX 10.12, *) {
timer = Timer.scheduledTimer(withTimeInterval: pollingInterval, repeats: true) { (_) in
self.polling()
}
} else {
timer = Timer.scheduledTimer(timeInterval: pollingInterval, target: self, selector: #selector(polling), userInfo: nil, repeats: true)
}
}
@objc private func polling() {
for device in self.devices {
if !device.isInProcess && device.isEnabled {
self.modbusQueue.async {
self.connectAndReadValues(device: device)
}
}
}
}
private func connectAndReadValues(device: Device) {
device.isInProcess = true
let connect = device.modbus.connect()
//handling connection status
//...
readValues(forDevice: device)
}
private func readValues(forDevice device: Device){
//some constants
do {
let registers = try device.modbus.readRegisters(from: startAddress, count: registersCount)
device.readState = .success
device.modbus.close()
//parse and save data to the app memory just as a dictionary. It saves only one small dictionary per device
parseRegisters(controllerIP: device.modbus.host, vendor: vendor, registers: registers, startAdd: startAddress)
} catch let error {
//handling errors
}
//refreshing interface in the main queue
}
【问题讨论】:
-
这只是一个崩溃。是什么原因造成的?什么代码?除非您可以创建展示此行为的最小测试用例,否则我们无法帮助您。如果你能做到,那么你应该提交一份错误报告。
-
@tadman,这就是问题所在。我不知道是什么代码造成的。该应用程序不会立即崩溃,它可以运行几个小时,而这个崩溃日志是我现在唯一的东西。
-
你有日志和代码。我们只有日志。仅此而已,真的无法确定这里发生了什么。我会看一下“同步操作中阻塞的调度线程太多”的措辞,看看是否有很多线程最终由于某种原因被阻塞。
-
@tadman,添加了一些可能导致崩溃的代码
-
您可能希望记录您发起的这些请求中有多少以及完成了多少。如果是频率问题,请设置一个测试模式,使其运行速度比现实生活中快 10 倍或 100 倍,以便更快地出现这些问题。