Ok, so I have an application that runs a pretty standard CoreData + MagicalRecord stack. He received one of them:
MagicalRecord.setupCoreDataStackWithAutoMigratingSqliteStoreAtURL(whisperStoreURL)
To perform operations with our CoreData model, we do two different things.
- MagicalRecord.saveWithBlock / MagicalRecord.saveWithBlockAndWait calls from the main or any other thread
- NSOperationQueue, a complete NSOperations that contains one call to MagicalRecord.saveWithBlockAndWait.
All this works very well, with the exception of a large production failure, the stack trace is lower. It seems like I'm violating CoreData's multithreading rules, except as far as I can tell, I don't know. Objects / Contexts are never passed between threads.
When CoreData concurrency debugging is enabled, on our local machines we sometimes get a multithreading violation (AllThatIsLeftToUsIsHonor), but it does not indicate anything as a reason. This may be related, or it may not be so.
I also tried connecting https://github.com/GrahamDennis/GDCoreDataConcurrencyDebugging to see if it provided more useful information about concurrency violations. It gives a lot of errors about what is releasecalled in another queue from the one on which the object was created, but, apparently, this is a false result.
I'm not even sure what the expression is still active. It seems like it works with multi-threaded problems, but I'm 99% sure that we are not breaking any rules.
, MagicalRecord . NSOperation , - , MR_saveToPersistentStoreAndWait.
, - , MagicalRecord, MR_saveToPersistentStoreAndWait , . , MagicalRecord/CoreData .
, , . , , .
( ) :
Fatal Exception: NSInternalInconsistencyException
statement is still active
Thread : Fatal Exception: NSInternalInconsistencyException
0 CoreFoundation 0x1844d1900 __exceptionPreprocess
1 libobjc.A.dylib 0x183b3ff80 objc_exception_throw
2 CoreData 0x185f32fbc -[NSSQLiteStatement cachedSQLiteStatement]
3 CoreData 0x185f327e4 -[NSSQLiteConnection prepareSQLStatement:]
4 CoreData 0x185f43020 -[NSSQLChannel selectRowsWithStatement:]
5 CoreData 0x18604534c newFetchedRowsForFetchPlan_MT
6 CoreData 0x185f3a7e4 -[NSSQLCore objectsForFetchRequest:inContext:]
7 CoreData 0x185f3a218 -[NSSQLCore executeRequest:withContext:error:]
8 CoreData 0x186001910 __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke
9 CoreData 0x186009d58 gutsOfBlockToNSPersistentStoreCoordinatorPerform
10 CoreData 0x185ffc5c8 _perform
11 CoreData 0x185f39e70 -[NSPersistentStoreCoordinator executeRequest:withContext:error:]
12 CoreData 0x185f38938 -[NSManagedObjectContext executeFetchRequest:error:]
13 CoreData 0x185fda318 -[NSManagedObjectContext(_NestedContextSupport) _parentObjectsForFetchRequest:inContext:error:]
14 CoreData 0x185fdaa44 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke
15 CoreData 0x185fcc76c _perform
16 CoreData 0x185fda824 -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]
17 CoreData 0x185f38938 -[NSManagedObjectContext executeFetchRequest:error:]
18 whisper 0x1003bd5bc __67+[NSManagedObject(MagicalRecord) MR_executeFetchRequest:inContext:]_block_invoke (NSManagedObject+MagicalRecord.m:54)
19 CoreData 0x185fd1080 developerSubmittedBlockToNSManagedObjectContextPerform
20 CoreData 0x185fd0f48 -[NSManagedObjectContext performBlockAndWait:]
21 whisper 0x1003bd500 +[NSManagedObject(MagicalRecord) MR_executeFetchRequest:inContext:] (NSManagedObject+MagicalRecord.m:50)
22 whisper 0x1003bd794 +[NSManagedObject(MagicalRecord) MR_executeFetchRequestAndReturnFirstObject:inContext:] (NSManagedObject+MagicalRecord.m:77)
23 whisper 0x1003bba84 +[NSManagedObject(MagicalFinders) MR_findFirstByAttribute:withValue:inContext:] (NSManagedObject+MagicalFinders.m:107)
24 whisper 0x1003bbdfc +[NSManagedObject(MagicalFinders) MR_findFirstOrCreateByAttribute:withValue:inContext:] (NSManagedObject+MagicalFinders.m:150)
25 whisper 0x10023325c specialized FetchWhispersForFeedResponseProcessor.processWhispers([String : AnyObject]) -> () (FetchWhispersForFeedResponseProcessor.swift:107)
26 whisper 0x100232250 FetchWhispersForFeedResponseProcessor.processStatusCode200() -> () (FetchWhispersForFeedResponseProcessor.swift:76)
27 whisper 0x10023199c FetchWhispersForFeedResponseProcessor.processWithLocalContext(NSManagedObjectContext) -> () (FetchWhispersForFeedResponseProcessor.swift:22)
28 whisper 0x100222d20 CoreDataResponseProcessor.(main(CoreDataResponseProcessor) -> () -> ()).(closure #1) (CoreDataResponseProcessor.swift:15)
29 whisper 0x1003b6144 __47+[MagicalRecord(Actions) saveWithBlockAndWait:]_block_invoke (MagicalRecord+Actions.m:48)
30 CoreData 0x185fd1080 developerSubmittedBlockToNSManagedObjectContextPerform
31 libdispatch.dylib 0x183f255f0 _dispatch_client_callout
32 libdispatch.dylib 0x183f3089c _dispatch_barrier_sync_f_invoke
33 CoreData 0x185fd0f68 -[NSManagedObjectContext performBlockAndWait:]
34 whisper 0x1003b60ac +[MagicalRecord(Actions) saveWithBlockAndWait:] (MagicalRecord+Actions.m:44)
35 whisper 0x100222a58 CoreDataResponseProcessor.main() -> () (CoreDataResponseProcessor.swift:16)
36 whisper 0x100222b9c @objc CoreDataResponseProcessor.main() -> () (CoreDataResponseProcessor.swift)
37 Foundation 0x184dbb348 -[__NSOperationInternal _start:]
38 Foundation 0x184e7a728 __NSOQSchedule_f
39 libdispatch.dylib 0x183f255f0 _dispatch_client_callout
40 libdispatch.dylib 0x183f31634 _dispatch_queue_drain
41 libdispatch.dylib 0x183f290f4 _dispatch_queue_invoke
42 libdispatch.dylib 0x183f33504 _dispatch_root_queue_drain
43 libdispatch.dylib 0x183f33224 _dispatch_worker_thread3
44 libsystem_pthread.dylib 0x184139470 _pthread_wqthread
45 libsystem_pthread.dylib 0x184139020 start_wqthread