I'm keeping something like memory-cache in NSMapTable:
// check for nils
if (key && image) {
// set object to NSMapTable
[_mapTable setObject:object forKey:key]; // crash
}
Unfortunately, lately I've got some problems with this method. Crash happens rather rarely, only on iOS 7. Crashlog indicates it happens at above line and shows more details:
-- Crashed: com.apple.root.default-priority ---
SIGABRT ABORT at 0x123456789
--- call stack ---
0
libsystem_kernel.dylib
__pthread_kill + 8
1
libsystem_pthread.dylib
pthread_kill + 58
2
libsystem_c.dylib
abort + 76
3
libsystem_malloc.dylib
free + 382
4
Foundation
-[NSConcreteMapTable grow] + 546
5
Foundation
-[NSConcreteMapTable setObject:forKey:] + 140
In fact, only 4 & 5 gives any info. I can't figure what's wrong in here. Because it happens in iOS7 only, maybe it's an Apple bug? Any ideas what can be the reason?
Related
I believe I've found a solution to the error, but don't understand if I'm just avoiding a race condition with my solution by slowing the code down or if I'm really solving the issue.
My question is 2 part
1) Why does changing dispatch.main.async to dispatch.main.sync make the error go away because I've coded it correctly or have I just worked around the issue for now?
2) Do I need to change all the dispatch.main.async to dispatch.main.sync for the 2 additional calls?
Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x600002a24180> was mutated while being enumerated.
In this report, the second answer specifically says, don't ever use dispatch.main.sync as it causes deadlocks. The first answer says, you may want to use sync but it can cause deadlocks.
What does main.sync in global().async mean?
Apple reports the error as follows:
Thread 5 name: Dispatch queue: com.apple.cloudkit.operation-7BCFBC195B4B17C3.callback
Thread 5 Crashed:
0 libsystem_kernel.dylib 0x00000001b4e120dc 0x1b4def000 + 143580
1 libsystem_pthread.dylib 0x00000001b4e8b094 0x1b4e89000 + 8340
2 libsystem_c.dylib 0x00000001b4d6af4c 0x1b4d10000 + 372556
3 libsystem_c.dylib 0x00000001b4d6aeb4 0x1b4d10000 + 372404
4 libc++abi.dylib 0x00000001b4437788 0x1b4436000 + 6024
5 libc++abi.dylib 0x00000001b4437934 0x1b4436000 + 6452
6 libobjc.A.dylib 0x00000001b444ee00 0x1b4449000 + 24064
7 libc++abi.dylib 0x00000001b4443838 0x1b4436000 + 55352
8 libc++abi.dylib 0x00000001b44438c4 0x1b4436000 + 55492
9 libdispatch.dylib 0x00000001b4cb47e8 0x1b4c54000 + 395240
10 libdispatch.dylib 0x00000001b4c5d324 0x1b4c54000 + 37668
11 libdispatch.dylib 0x00000001b4c5de74 0x1b4c54000 + 40564
12 libdispatch.dylib 0x00000001b4c664ac 0x1b4c54000 + 74924
13 libsystem_pthread.dylib 0x00000001b4e95114 0x1b4e89000 + 49428
14 libsystem_pthread.dylib 0x00000001b4e97cd4 0x1b4e89000 + 60628
When I run the code in Xcode, I can reproduce the error in Xcode and get the following stack trace.
2019-07-31 19:51:07.893799-0400 My Toy Chest[49278:1080065] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x600002a24180> was mutated while being enumerated.'
*** First throw call stack:
(
0 CoreFoundation 0x00000001106d38db __exceptionPreprocess + 331
1 libobjc.A.dylib 0x000000010f6f4ac5 objc_exception_throw + 48
2 CoreFoundation 0x00000001106d07ac __NSFastEnumerationMutationHandler + 124
3 CoreData 0x0000000110048dd4 -[NSManagedObjectContext executeFetchRequest:error:] + 3332
4 My Toy Chest 0x0000000109248bc0 $s12My_Toy_Chest21ActionFigureSpecificsC03setdeF8CoreDataSbyF + 1472
5 My Toy Chest 0x000000010923a4b2 $s12My_Toy_Chest21ActionFigureSpecificsC03setdeF0yyF + 546
6 My Toy Chest 0x0000000109313c6b $s12My_Toy_Chest22SharedDataActionFigureC03getfg26SpecificsICloudForCompletefG5ArrayyyFySaySo8CKRecordCGSg_s5Error_pSgtcfU_ + 3051
7 My Toy Chest 0x000000010931409c $s12My_Toy_Chest22SharedDataActionFigureC03getfg26SpecificsICloudForCompletefG5ArrayyyFySaySo8CKRecordCGSg_s5Error_pSgtcfU_TA + 12
8 My Toy Chest 0x0000000109315233 $s12My_Toy_Chest22SharedDataActionFigureC013fetchCompletefG18SpecificsFromCloud10completionyySaySo8CKRecordCGSg_s5Error_pSgtc_tFySo13CKQueryCursorCSg_AKtcfU0_ + 1331
9 My Toy Chest 0x0000000109315e01 $s12My_Toy_Chest22SharedDataActionFigureC013fetchCompletefG18SpecificsFromCloud10completionyySaySo8CKRecordCGSg_s5Error_pSgtc_tFySo13CKQueryCursorCSg_AKtcfU0_TA + 49
10 My Toy Chest 0x00000001092373b4 $sSo13CKQueryCursorCSgs5Error_pSgIeggg_ACSo7NSErrorCSgIeyByy_TR + 132
11 CloudKit 0x000000010f51e84d -[CKQueryOperation _finishOnCallbackQueueWithError:] + 613
12 CloudKit 0x000000010f51795a -[CKOperation _finishInternalOnCallbackQueueWithError:] + 582
13 CloudKit 0x000000010f5176fa -[CKOperation _handleCompletionCallback:] + 148
14 CloudKit 0x000000010f51e521 -[CKQueryOperation _handleCompletionCallback:] + 197
15 CloudKit 0x000000010f58d438 __82-[CKOperationCallbackManager _performCallbackForOperation:callback:errorCallback:]_block_invoke + 288
16 libdispatch.dylib 0x000000011189e725 _dispatch_block_async_invoke2 + 83
17 libdispatch.dylib 0x0000000111890db5 _dispatch_client_callout + 8
18 libdispatch.dylib 0x0000000111898225 _dispatch_lane_serial_drain + 778
19 libdispatch.dylib 0x0000000111898ed0 _dispatch_lane_invoke + 477
20 libdispatch.dylib 0x00000001118a2ea3 _dispatch_workloop_worker_thread + 733
21 libsystem_pthread.dylib 0x0000000111c79611 _pthread_wqthread + 421
22 libsystem_pthread.dylib 0x0000000111c793fd start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
I am pretty sure the code where the defect is occurring is the following set of code that updates the UI in a View Controller collection view.
The following code crashes (async)
DispatchQueue.main.async {
self.delegate?.updateActionFigureSpecificsModel()
}
The following code doesn't crash (sync)
DispatchQueue.main.sync {
self.delegate?.updateActionFigureSpecificsModel()
}
Subsequent calls that update the View Controller collection views
func updateActionFigureSpecificsModel() {
DispatchQueue.main.async {
self.delegate?.updateActionFigureModel(forActionFigure: self, forDelegateProperty: .specifics)
}
}
func updateActionFigureModel(forActionFigure actionFigure: ActionFigure, forDelegateProperty delegateProperty: DelegateProperty) {
switch delegateProperty {
case .specifics, .eBaySaleSummary:
DispatchQueue.main.async {
self.setUIActionFigure(forActionFigure: actionFigure)
}
}
}
func setUIActionFigure(forActionFigure actionFigure: ActionFigure) {
if let indexPath = getIndexPath(forActionFigure: actionFigure) {
DispatchQueue.main.async {
self.collectionView.reloadItems(at: [indexPath])
}
}
I really can't tell from what you've posted what the exact problem is, but you're probably running into one or both of these general issues:
Foundation collections are not thread-safe and cannot be modified from multiple threads.
A foundation collection cannot be modified while it is being iterated.
I suspect that the collection you're using/iterating/modifying in whatever thread you're running is colliding with whatever use/iteration/modification that's being done by the tasks you're dispatching on main. And yes, I suspect that changing async to sync is just dodging the issue by waiting for the main task to complete before the background thread resumes. As a rule, if the background thread and main thread are sharing a reference to the same foundation collection–and either of them modify that collection–you're going to eventually run into problems ... unless you're very, very, careful.
A solution I often use is to keep my collections separate. My background thread will make updates or perform calculations that update a collection. Then I'll make a copy of the collection and pass that copy to main for display and UI interactions.
In my iPad app I often get a crash report with the exception EXC_RESOURCE and the subtype WAKEUPS.
However the strange thing is that the message says (Limit 150/sec) Observed 0/sec over 300 sec
How can it become an exception when it observed 0 wakeups/sec? - and how do I avoid it?
The reason I care is that the generation of the report delays some time critical threads in the app.
Mainly are we recording from the microphone and playing audio at the same time, and while the report is generated, the audio stutters.
The exception is always triggered by one of 3 threads: Main thread, AURemoteIO: IOThread and com.apple.coreaudio.AQClient. See fragments of report below:
Hardware Model: iPad2,5
Code Type: ARM (Native)
Parent Process: debugserver [3109]
Date/Time: 2016-05-18 12:15:59.59 +0200
Launch Time: 2016-05-18 12:11:44.44 +0200
OS Version: iOS 9.1 (13B143)
Report Version: 104
Exception Type: EXC_RESOURCE
Exception Subtype: WAKEUPS
Exception Message: (Limit 150/sec) Observed 0/sec over 300 secs
Exception Note: NON-FATAL CONDITION (this is NOT a crash)
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Attributed:
0 CoreFoundation 0x25ef8c4e 0x25ef6000 + 11342
1 CoreFoundation 0x25fab760 0x25ef6000 + 743264
...
Thread 10 name: AURemoteIO::IOThread
Thread 10:
0 libsystem_kernel.dylib 0x382acff0 mach_msg_trap + 20
1 libsystem_kernel.dylib 0x382acdf4 mach_msg + 40
2 AudioToolbox 0x2544ec50 AURemoteIO::IOThread::Run() + 104
3 AudioToolbox 0x25452500 AURemoteIO::IOThread::Entry(void*) + 8
4 AudioToolbox 0x25369fee CAPThread::Entry(CAPThread*) + 186
5 libsystem_pthread.dylib 0x3836385a _pthread_body + 138
6 libsystem_pthread.dylib 0x383637ce _pthread_start + 110
7 libsystem_pthread.dylib 0x38361724 thread_start + 8
...
Thread 12 name: com.apple.coreaudio.AQClient
Thread 12:
0 libsystem_kernel.dylib 0x382acff0 mach_msg_trap + 20
1 libsystem_kernel.dylib 0x382acdf4 mach_msg + 40
2 CoreFoundation 0x25fad8c4 __CFRunLoopServiceMachPort + 136
3 CoreFoundation 0x25fabc4c __CFRunLoopRun + 1036
4 CoreFoundation 0x25eff118 CFRunLoopRunSpecific + 520
5 CoreFoundation 0x25efef04 CFRunLoopRunInMode + 108
6 AudioToolbox 0x253810b4 GenericRunLoopThread::Entry(void*) + 132
7 AudioToolbox 0x25369fee CAPThread::Entry(CAPThread*) + 186
8 libsystem_pthread.dylib 0x3836385a _pthread_body + 138
9 libsystem_pthread.dylib 0x383637ce _pthread_start + 110
10 libsystem_pthread.dylib 0x38361724 thread_start + 8
The main confusion was the Observed 0/sec statement, but I found that this number was wrong. When running the same code on a newer and faster iPad it suddenly showed a number here (200-400), so it was simply due to a slow iPad that it could not calculate a number.
Secondly I found that there was indeed a thread that was starting and stopping way too often, but it was not the one that triggered the error, so that made it a lot more difficult to locate.
A customer of my app sent me this strange crash report and I cannot figure out how this could ever crash. I cannot reproduce the problem myself, so am reliant on the crash report.
It crashes on the following very simple line of code:
UITextField *value = [[UITextField alloc] initWithFrame:frame];
The crash seems to be related to key-value-observing (KVO), but I am not doing anything with that here; it's a simply constructor!
The only possibility I could see, is that another thread is writing to a dealloc'ed object that happens to have the same memory address as an object that is created by the initWithFrame:. But in the crash report, all other threads are quiet.
I have found other similar questions, but none of them have an answer.
Any ideas?
Here are the relevant parts from the crash report:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000010
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x0000000181981b90 objc_msgSend + 16
1 Foundation 0x0000000182bf2454 -[NSObject(NSKeyValueObserverNotification) willChangeValueForKey:] + 324
2 QuartzCore 0x0000000184deb11c CA::Layer::set_delegate(objc_object*) + 72
3 UIKit 0x0000000187456f40 -[UIView _createLayerWithFrame:] + 580
4 UIKit 0x0000000187456a00 UIViewCommonInitWithFrame + 688
5 UIKit 0x00000001874566f0 -[UIView initWithFrame:] + 140
6 UIKit 0x000000018745dfb0 -[UILabel initWithFrame:] + 48
7 UIKit 0x0000000187542064 -[UITextField createTextLabelWithTextColor:] + 76
8 UIKit 0x0000000187541c30 -[UITextField initWithFrame:] + 416
9 Flyskyhy 0x00000001000e1f68 -[ElementView doInitWithUnit:] (ElementView.m:178)
I am usually able to solve the crashes but here I have not clue from where it comes from.
I use parse, and I am simply doing a request in background with a completion block.
The app crashes at a simple if condition and I can barely identify anything, no way to print description, ...
Do you have any idea ? A starting point ? anything ?
Xcode 6.1 is really strange, it seems that the debugger is buggy.
Here is the log of the crash :
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x000000019657a964 __kill + 8
1 MyAPP 0x00000001001f2b70 0x10009c000 + 1403760
2 libsystem_platform.dylib 0x0000000196610958 _sigtramp + 64
3 MyAPP 0x00000001001318cc 0x10009c000 + 612556
4 MyAPP 0x000000010013797c 0x10009c000 + 637308
5 MyAPP 0x0000000100135fc4 0x10009c000 + 630724
6 MyAPP 0x00000001002e408c 0x10009c000 + 2392204
7 MyAPP 0x00000001001dbf78 0x10009c000 + 1310584
8 libdispatch.dylib 0x00000001964393a8 _dispatch_call_block_and_release + 20
9 libdispatch.dylib 0x0000000196439368 _dispatch_client_callout + 12
10 libdispatch.dylib 0x000000019643d97c _dispatch_main_queue_callback_4CF + 928
11 CoreFoundation 0x000000018566d69c __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
12 CoreFoundation 0x000000018566b744 __CFRunLoopRun + 1488
13 CoreFoundation 0x00000001855991f0 CFRunLoopRunSpecific + 392
14 GraphicsServices 0x000000018e7275a0 GSEventRunModal + 164
15 UIKit 0x0000000189eca780 UIApplicationMain + 1484
16 Shuff 0x0000000100129474 0x10009c000 + 578676
17 libdyld.dylib 0x0000000196462a04 start + 0
And here is a sample of the iOS code :
var query = PFQuery(className: "_User")
query.whereKey("facebookId", containedIn: ids)
query.findObjectsInBackgroundWithBlock(){
results, error in
if var resultsvar = results? {
self.functionToCall(resultsvar)
}
}
and the functionToCall crashes.
Maybe this can help :
0 0x00000001001679c8 in specialization of Swift._ArrayBuffer._nonNative.getter : Swift.Optional [inlined] ()
Yes !!! The debugger is not working well ! I was able to find the correct lines by doing the following : put a breakpoint at the start of where you think the app crashes, go step by step, remember the lowest line you've gone through. Even if the debugger crashes on another the line, the line you are looking for is probably the lowest one.
This is just a guess but I was working on something similar and I think you need to change this code to:
query.findObjectsInBackgroundWithBlock(){
results?, error? in
if var resultsvar = results {
self.functionToCall(resultsvar)
}
}
Note that I made both results and error optional. In my case I was providing a block defined in Obj-C, and in Obj-C these objects can legally be == nil. So I think you have to define them as optionals in Swift.
I got a crash log from a user, and I do not see any function names - only pointers in hex:
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x30a29c98 0x30a27000 + 11416
1 UIKit 0x3517b4ee 0x35167000 + 83182
2 UIKit 0x3518eddc 0x35167000 + 163292
3 UIKit 0x3523a84a 0x35167000 + 866378
4 CoreFoundation 0x32368c3c 0x32366000 + 11324
5 UIKit 0x3517b5ee 0x35167000 + 83438
6 UIKit 0x3518eddc 0x35167000 + 163292
7 UIKit 0x3523a70c 0x35167000 + 866060
How can I get the crash log to show more meaningful info ?
This should point you in the right direction:
Technical Note TN2151 - Understanding and Analyzing iPhone OS Application Crash Reports