I have been getting a strange crash reported by lots of users through HockeyApp with the following stack trace. It seems to have something to do with NSManagedObject being released in a different dispatch queue ... but I don't get any symbolication for where the problem might be. It seems like a memory management issue, but I'm using ARC so not sure how it would over-release an NSManagedObject.
This is the crash report I get (the main thread shows different traces at different times):
Code Type: ARM-64
Parent Process: launchd [1]
Date/Time: 2014-05-12T05:43:54Z
OS Version: iPhone OS 7.0.6 (11B651)
Report Version: 104
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR at 0x1c3dbeb8
Crashed Thread: 2
Application Specific Information:
objc_msgSend() selector name: _queueForDealloc:
Thread 0:
0 CoreFoundation 0x000000018e384618 CFNumberGetType + 0
1 CoreFoundation 0x000000018e3333b8 _CFAppendXML0 + 2768
2 CoreFoundation 0x000000018e333304 _CFAppendXML0 + 2588
3 CoreFoundation 0x000000018e332268 _CFPropertyListCreateXMLData + 196
4 Foundation 0x000000018ef152f4 -[NSDictionary(NSDictionary) writeToFile:atomically:] + 232
5 SimpleList 0x00000001001ae48c __55-[SharedSettingController writeToContactsReferenceFile]_block_invoke (SharedSettingController.m:620)
6 libdispatch.dylib 0x000000019a974420 _dispatch_call_block_and_release + 20
7 libdispatch.dylib 0x000000019a9743e0 _dispatch_client_callout + 12
8 libdispatch.dylib 0x000000019a97756c _dispatch_main_queue_callback_4CF + 340
9 CoreFoundation 0x000000018e3e6d64 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
10 CoreFoundation 0x000000018e3e50a4 __CFRunLoopRun + 1448
11 CoreFoundation 0x000000018e325b38 CFRunLoopRunSpecific + 448
12 GraphicsServices 0x0000000193d4b830 GSEventRunModal + 164
13 UIKit 0x00000001913640e8 UIApplicationMain + 1152
14 SimpleList 0x000000010006347c _mh_execute_header (main.m:18)
15 libdyld.dylib 0x000000019a98faa0 start + 0
Thread 1:
0 libsystem_kernel.dylib 0x000000019aa71ac8 kevent64 + 8
1 libdispatch.dylib 0x000000019a975d78 _dispatch_mgr_thread + 48
Thread 2 Crashed:
0 libobjc.A.dylib 0x000000019a39f9d0 objc_msgSend + 16
1 CoreData 0x000000018e13b284 -[NSManagedObject release] + 168
2 CoreData 0x000000018e131154 -[_PFArray dealloc] + 96
3 libobjc.A.dylib 0x000000019a3a13d4 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 520
4 libdispatch.dylib 0x000000019a97b428 _dispatch_root_queue_drain + 440
5 libdispatch.dylib 0x000000019a97b638 _dispatch_worker_thread2 + 72
6 libsystem_pthread.dylib 0x000000019ab09918 _pthread_wqthread + 352
7 libsystem_pthread.dylib 0x000000019ab097a8 start_wqthread + 0
Thread 3:
0 libsystem_kernel.dylib 0x000000019aa71cc0 mach_msg_trap + 8
1 CoreFoundation 0x000000018e3e6cac __CFRunLoopServiceMachPort + 180
2 CoreFoundation 0x000000018e3e4e3c __CFRunLoopRun + 832
3 CoreFoundation 0x000000018e325b38 CFRunLoopRunSpecific + 448
4 Foundation 0x000000018ef127fc +[NSURLConnection(Loader) _resourceLoadLoop:] + 344
5 Foundation 0x000000018efa0770 __NSThread__main__ + 996
6 libsystem_pthread.dylib 0x000000019ab0c1b0 _pthread_body + 164
7 libsystem_pthread.dylib 0x000000019ab0c108 _pthread_start + 136
8 libsystem_pthread.dylib 0x000000019ab097b0 thread_start + 0
Thread 4:
0 libsystem_kernel.dylib 0x000000019aa8a76c __select + 8
1 libsystem_pthread.dylib 0x000000019ab0c1b0 _pthread_body + 164
2 libsystem_pthread.dylib 0x000000019ab0c108 _pthread_start + 136
3 libsystem_pthread.dylib 0x000000019ab097b0 thread_start + 0
Thread 5:
0 libsystem_kernel.dylib 0x000000019aa8ae74 __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x000000019ab097a8 start_wqthread + 0
Thread 6:
0 libsystem_kernel.dylib 0x000000019aa8ae74 __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x000000019ab097a8 start_wqthread + 0
Thread 7:
0 libsystem_kernel.dylib 0x000000019aa8ae74 __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x000000019ab097a8 start_wqthread + 0
Thread 2 crashed with ARM-64 Thread State:
pc: 0x000000019a39f9d0 fp: 0x0000000102b479c0 sp: 0x0000000102b479a0 x0: 0x00000001782451f0
x1: 0x000000018e2eeb56 x2: 0x00000001705336a0 x3: 0x000000019aac3d18 x4: 0x0000000000000001
x5: 0x0000000000000010 x6: 0x000000017013f900 x7: 0x0000000000000000 x8: 0x000000019ad5bdb8
x9: 0x000000001c3dbea8 x10: 0x0000000000000000 x11: 0x000000230000003f x12: 0x000000014f073410
x13: 0xbadd5bcc1c3dbead x14: 0xffffffffffffffff x15: 0x0000000000000001 x16: 0x000000019a39f9c0
x17: 0x000000018e13b1d8 x18: 0x0000000000000000 x19: 0x00000001705336a0 x20: 0x000000019ad7b000
x21: 0x000000019adc9200 x22: 0x000000019ad7b000 x23: 0x0000000000000715 x24: 0x0000000000000010
x25: 0x0000000102a64038 x26: 0xa3a3a3a3a3a3a3a3 x27: 0x0000000000000001 x28: 0x0000000000000000
lr: 0x000000018e13b284 cpsr: 0x0000000020000000
At launch, I do initiate a couple of dispatch queues to do some background work (they use a separate MOC to load managed objects and process them), so those might be responsible, but the queues are labelled in my app, and the stack trace doesn't seem to show which queue is responsible (if it is my own queues). I've run the app with NSZombies enabled but that doesn't help. I have also ran the static analysis tool, and that doesn't turn up anything.
Any ideas what might be causing this problem, and what I can do to debug it?
EDIT:
I'm pretty sure I can isolate the problem area down to a piece of code that gets called after launching the app:
SLAppDelegate *delegate = (SLAppDelegate *) [[UIApplication sharedApplication] delegate];
dispatch_async(delegate.coreDataController.filterMainQueue, ^{
NSManagedObjectContext *backgroundContextImage = [[NSManagedObjectContext alloc] init];
[backgroundContextImage setPersistentStoreCoordinator: delegate.coreDataController.persistentStoreCoordinator];
NSArray *items = [Person getAllPersonsWithContext: backgroundContextImage];
// possibly update some of the items
dispatch_async(dispatch_get_main_queue(), ^{
// writes the file inside another dispatch_asyn(dispatch_get_main_queue)
[[SharedSettingController sharedSettings] writeToContactsReferenceFile];
};
});
I'm just not sure what is wrong with this. It works fine 99% of the time. But that 1% is causing a few crashes that I'd love to get resolved.
We hit into a a similar issue when using a private managed object context inside an NSOperation
and we ended up working around it by weakifying any parameters and using a private @autoreleasepool
. I'll elaborate further below.
Our current set up has an NSOperationQueue
which has a long running calculation we do in the background. The operation first creates a private managed object context with the parent set as the main object context and goes and fetches its objects.
In the mean time, we have a separate NSOperationQueue
elsewhere that syncs down new data from our server, potentially adding, updating, or removing objects used by our calculation operation.
We first saw a bunch of these crashes out in the wild and the only way to repro it locally is to have both calculation and sync operations run continuously and after 5-10 minutes, we would see a crash similar to one of the below:
Thread : Crashed: background queue :: NSOperation 0x18f43c90
0 libobjc.A.dylib 0x36f11f46 objc_msgSend + 5
1 CoreData 0x2928408f -[NSManagedObject release] + 166
2 CoreData 0x2927b4d7 -[_PFArray dealloc] + 94
3 libobjc.A.dylib 0x36f201a9 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 404
4 CoreFoundation 0x294713a9 _CFAutoreleasePoolPop + 16
5 Foundation 0x2a1b6453 -[__NSOperationInternal _start:] + 1058
6 Foundation 0x2a25b44b __NSOQSchedule_f + 186
7 libdispatch.dylib 0x3746d651 _dispatch_queue_drain + 952
8 libdispatch.dylib 0x3746809d _dispatch_queue_invoke + 84
9 libdispatch.dylib 0x3746eba1 _dispatch_root_queue_drain + 320
10 libdispatch.dylib 0x3746fcd7 _dispatch_worker_thread3 + 94
11 libsystem_pthread.dylib 0x375c6e31 _pthread_wqthread + 668
Thread : Crashed: background queue :: NSOperation 0x1db59e80
0 libsystem_kernel.dylib 0x3722edfc __pthread_kill + 8
1 libsystem_pthread.dylib 0x372acd37 pthread_kill + 62
2 libsystem_c.dylib 0x371ce909 abort + 76
3 libsystem_malloc.dylib 0x37258331 szone_size
4 libobjc.A.dylib 0x36bf1621 object_dispose + 20
5 CoreData 0x28ec571d -[_PFManagedObjectReferenceQueue dealloc] + 80
6 CoreData 0x28e5630f -[NSManagedObject dealloc] + 166
7 CoreData 0x28e55217 -[_PFManagedObjectReferenceQueue _queueForDealloc:] + 246
8 CoreData 0x28e5508f -[NSManagedObject release] + 166
9 CoreData 0x28e4c4d7 -[_PFArray dealloc] + 94
10 libobjc.A.dylib 0x36c031a9 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 404
11 CoreFoundation 0x29042149 _CFAutoreleasePoolPop + 16
12 Foundation 0x29d88c23 -[__NSOperationInternal _start:] + 1058
13 Foundation 0x29e2dc1b __NSOQSchedule_f + 186
14 libdispatch.dylib 0x371505b1 _dispatch_queue_drain + 952
15 libdispatch.dylib 0x3714af85 _dispatch_queue_invoke + 84
16 libdispatch.dylib 0x37151b9b _dispatch_root_queue_drain + 338
17 libdispatch.dylib 0x37152cd7 _dispatch_worker_thread3 + 94
18 libsystem_pthread.dylib 0x372a9e31 _pthread_wqthread + 668
Thread : Crashed: NSOperationQueue Serial Queue
0 libsystem_kernel.dylib 0x396871f0 __pthread_kill + 8
1 libsystem_pthread.dylib 0x396ef7b7 pthread_kill + 58
2 libsystem_c.dylib 0x39637ff9 abort + 76
3 libsystem_malloc.dylib 0x396aed25 szone_size
4 libobjc.A.dylib 0x390d93a9 object_dispose + 20
5 CoreData 0x2e3d4081 -[_PFManagedObjectReferenceQueue dealloc] + 80
6 CoreData 0x2e3655b7 -[NSManagedObject dealloc] + 166
7 CoreData 0x2e364501 -[_PFManagedObjectReferenceQueue _queueForDealloc:] + 244
8 CoreData 0x2e36437d -[NSManagedObject release] + 164
9 CoreData 0x2e35b867 -[_PFArray dealloc] + 94
10 libobjc.A.dylib 0x390e20d3 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 358
11 CoreFoundation 0x2e5294c1 _CFAutoreleasePoolPop + 16
12 Foundation 0x2ef29999 -[__NSOperationInternal _start:] + 1064
13 Foundation 0x2efcd745 __NSOQSchedule_f + 60
14 libdispatch.dylib 0x395c0cbd _dispatch_queue_drain + 488
15 libdispatch.dylib 0x395bdc6f _dispatch_queue_invoke + 42
16 libdispatch.dylib 0x395c15f1 _dispatch_root_queue_drain + 76
17 libdispatch.dylib 0x395c18dd _dispatch_worker_thread2 + 56
18 libsystem_pthread.dylib 0x396ecc17 _pthread_wqthread + 298
We reviewed the code multiple times and was not able to determine why it was crashing. We tried enabling NSZombies, but would run out of memory long before we could get a repro.
What we ended up doing is the following 2 things:
@autoreleasepool
Inside our [privateObjectContext performBlockAndWait:^{…}]
which resides inside our NSOperationBlock
, we wrapped all the code inside an @autoreleasepool{…}
. That way all NSManagedObjects retrieved during that block of code will be mark for release before leaving the performBlockAndWait.
weakify/strongify
Any parameters that include NSManagedObjects were weakify before passing it into the block, and strongify once in the block. This way since we no longer have a strong reference to them, they can be released if they become out of date while we wait for the NSOperation
to start. Here's a good article on how weakify/strongify works: http://blog.aceontech.com/post/111694918560/weakifyself-a-more-elegant-solution-to
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With