I've got a stack trace showing a crash responding to a memory warning:
Thu Oct 28 00:42:55 iPhone DTMobileIS[10853] : _memoryNotification : {name = (null), num = 1} Thu Oct 28 00:42:55 iPhone DTMobileIS[10853] : _memoryNotification : { OSMemoryNotificationLevel = 1; timestamp = "2010-10-28 07:42:55 GMT"; } Thu Oct 28 00:42:55 iPhone MyApp[11059] : Received memory warning. Level=1 Thu Oct 28 00:42:55 iPhone MyApp[11059] : -[__NSCFType tryLock]: unrecognized selector sent to instance 0x41bfd0 Thu Oct 28 00:42:55 iPhone MyApp[11059] : *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType tryLock]: unrecognized selector sent to instance 0x41bfd0' *** Call开发者_运维问答 stack at first throw: ( 0 CoreFoundation 0x30897ed3 __exceptionPreprocess + 114 1 libobjc.A.dylib 0x3002f811 objc_exception_throw + 24 2 CoreFoundation 0x30899683 -[NSObject(NSObject) doesNotRecognizeSelector:] + 102 3 CoreFoundation 0x308411d9 ___forwarding___ + 508 4 CoreFoundation 0x30840f90 _CF_forwarding_prep_0 + 48 5 CoreData 0x316cc261 -[_NSSQLCoreConnectionObsever _purgeCaches:] + 124 6 Foundation 0x349bb6b3 _nsnote_callback + 142 7 CoreFoundation 0x3081e713 __CFXNotificationPost_old + 402 8 CoreFoundation 0x3081e3b3 _CFXNotificationPostNotification + 118 9 Foundation 0x349aadb7 -[NSNotificationCenter postNotificationName:object:userInfo:] + 70 10 Foundation 0x349b42d1 -[NSNotificationCenter postNotificationName:object:] + 24 11 UIKit 0x31ed9431 -[UIApplication _performMemoryWarning] + 48 12 UIKit 0x31ec7383 -[UIApplication _receivedMemoryNotification] + 126 13 UIKit 0x31ec72c7 _memoryStatusChanged + 42 14 CoreFoundation 0x3084e825 __CFNotificationCenterDarwinCallBack + 24 15 CoreFoundation 0x30835313 __CFMachPortPerform + 210 16 CoreFoundation 0x3082cce3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26 17 CoreFoundation 0x3082cca7 __CFRunLoopDoSource1 + 166 18 CoreFoundation 0x3081f56d __CFRunLoopRun + 520 19 CoreFoundation 0x3081f277 CFRunLoopRunSpecific + 230 20 CoreFoundation 0x3081f17f CFRunLoopRunInMode + 58 21 GraphicsServices 0x31e445f3 GSEventRunModal + 114 22 GraphicsServices 0x31e4469f GSEventRun + 62 23 UIKit 0x31e51123 -[UIApplication _run] + 402 24 UIKit 0x31e4f12f UIApplicationMain + 670 25 MyApp 0x00052c81 main + 72 26 MyApp 0x00002f18 start + 52 )
I'm not really sure what core data was doing that it tried to obtain a lock from this object, however I feel like this is indicative of a threading issue somewhere inside my code.
Can anyone think of a good way to debug this or possible root causes?
I ran into this recently and found a solution. The bug is in Core Data itself, and manifests in versions prior to iOS 5.1 (it appears to be fixed in that version).
The crash happens when the persistent store coordinator (PSC) fails to load a given persistent store (say because the schema changed). In this case, the failed store still appears to be added to an internal Core Data cache, even though there is no external access to it. This cache is then flushed automatically by Core Data when the app is backgrounded, or in certain memory pressure situations. Everything is fine unless you the PSC that was used to try to load the failed store has since been deallocated, in which case the cache will try to access it and give the above error.
So, to summarize, you will hit this error in this situation:
- Try and fail to load a persistent store from disk. This will likely happen because you've upgraded your app and the model schema changed.
- Deallocate the persistent store coordinator you used to to try to load the store.
- Background the app, or in some cases trigger a memory warning.
- Crash
To work around this problem there are two options. I chose to simply not deallocate the PSC in the case of a failed call to -addPersistentStoreWithType:configuration:URL:options:error:, in which case the cache purge will still access a valid PSC. An alternative is to preemptively check that the model schema matches the on-disk persistent store's scheme using the following two calls:
+[NSPersistentStore metadataForPersistentStoreWithURL:error:]
-[NSManagedObjectModel isConfiguration:compatibleWithStoreMetadata:]
The second solution may avoid leaking a PSC in certain rare cases, but also assumes that the only possible way that a persistent store will fail to load is because of mismatched model schemas.
I actually found, after a bit of code analysis, the root cause of this appears to be crossing threads with CoreData. I had a background thread from an operation queue manipulating a NSManagedObjectContext which originated on the main thread (and caused a save! ouch!).
After a few of these manipulations if I sent a memory warning in the simulator the app would crash.
精彩评论