核心数据嵌套的托管对象上下文和频繁的死锁/冻结

the*_*jaz 30 core-data objective-c nsfetchedresultscontroller nsmanagedobjectcontext ios

我有一个问题几乎与此人描述的问题相同,但它没有得到答案:

http://www.cocoabuilder.com/archive/cocoa/312683-core-data-nested-managed-object-contexts-and-frequent-deadlocks.html#312683

这是问题所在:

我有一个使用NSPrivateQueueConcurrencyType和持久性存储协调器集的父MOC设置,它有一个带有NSMainQueueConcurrencyType的子MOC设置.大多数长期努力工作和保存的想法可以在私有MOC上完成,从而使主线程阻止UI.不幸的是,我似乎遇到了导致死锁的几种情况.

如果子MOC(在主线程上)正在使用NSFetchedResultsController执行提取,则会向父上下文发送-executeFetchRequest:它可以创建死锁.这两个操作都是在performBlock的上下文中完成的:对于它们各自的MOC,尽管文档似乎表明在没有performBlock的主线程上使用主线程并发类型MOC是好的.

看起来私有队列正在等待主线程上的子上下文已经锁定的PSC锁.看起来子上下文(在持有PSC锁定时)试图将dispatch_sync分配给父上下文,因此它们都在等待彼此.

是PriveQueue - > MainQueue是支持的配置吗?似乎大多数人仍然在主线程上有父上下文.

主线程看起来像这样:

> #0    0x960f6c5e in semaphore_wait_trap ()
> #1    0x04956bb5 in _dispatch_thread_semaphore_wait ()
> #2    0x04955c8f in _dispatch_barrier_sync_f_slow ()
> #3    0x04955dea in dispatch_barrier_sync_f ()
> #4    0x01797de5 in _perform ()
> #5    0x01798547 in -[NSManagedObjectContext(_NestedContextSupport) newValuesForObjectWithID:withContext:error:] ()
> #6    0x0176416b in _PFFaultHandlerLookupRow ()
> #7    0x01763f97 in -[NSFaultHandler fulfillFault:withContext:forIndex:] ()
> #8    0x01763b75 in _PF_FulfillDeferredFault ()
> #9    0x017639f2 in _sharedIMPL_pvfk_core ()
> #10    0x017681a0 in _pvfk_11 ()
> #11    0x0001b322 in -[FBUser sectionName] at /Users/mlink/Code/x/x/FBUser.m:62
> #12    0x011a8813 in _NSGetUsingKeyValueGetter ()
> #13    0x017a0652 in -[NSManagedObject valueForKey:] ()
> #14    0x011ab8d5 in -[NSObject(NSKeyValueCoding) valueForKeyPath:] ()
> #15    0x01851f72 in -[NSFetchedResultsController(PrivateMethods) _sectionNameForObject:] ()
> #16    0x01853af6 in -[NSFetchedResultsController(PrivateMethods) _computeSectionInfo:error:] ()
> #17    0x01850ea6 in -[NSFetchedResultsController performFetch:] ()
> #18    0x0003a4fc in __62-[SYFriendsTableViewController updateFetchedResultsController]_block_invoke_0 ()
> #19    0x01797af3 in developerSubmittedBlockToNSManagedObjectContextPerform ()
> #20    0x049554f0 in _dispatch_main_queue_callback_4CF ()
> #21    0x01b3e833 in __CFRunLoopRun ()
> #22    0x01b3ddb4 in CFRunLoopRunSpecific ()
> #23    0x01b3dccb in CFRunLoopRunInMode ()
> #24    0x023d6879 in GSEventRunModal ()
> #25    0x023d693e in GSEventRun ()
> #26    0x0089aa9b in UIApplicationMain ()
> #27    0x00002656 in main at /Users/mlink/Code/x/x/main.mm:16
Run Code Online (Sandbox Code Playgroud)

私有队列堆栈如下所示:

#0    0x960f8876 in __psynch_mutexwait ()
#1    0x97e9e6af in pthread_mutex_lock ()
#2    0x0172ec22 in -[_PFLock lock] ()
#3    0x0172ebfa in -[NSPersistentStoreCoordinator lock] ()
#4    0x01746a8c in -[NSManagedObjectContext(_NSInternalAdditions) lockObjectStore] ()
#5    0x01745030 in -[NSManagedObjectContext executeFetchRequest:error:] ()
#6    0x0009d49f in -[NSManagedObjectContext(Additions) executeFetchRequest:] at /Users/mlink/Code/objc/C/C/NSManagedObjectContext+Additions.m:44
#7    0x0002177f in +[FBUser usersForFbids:inManagedObjectContext:] at /Users/mlink/Code/x/x/FBUser.m:435
#8    0x00021fc0 in __77+[FBUser updateUserFromGraphValues:inManagedObjectContext:completionHandler:]_block_invoke_0 at /Users/mlink/Code/x/x/FBUser.m:461
#9    0x0180f9f3 in developerSubmittedBlockToNSManagedObjectContextPerform_privateasync ()
#10    0x04954ecf in _dispatch_queue_drain ()
#11    0x04954d28 in _dispatch_queue_invoke ()
#12    0x049544af in _dispatch_worker_thread2 ()
#13    0x97ea1b24 in _pthread_wqthread ()
#14    0x97ea36fe in start_wqthread ()
Run Code Online (Sandbox Code Playgroud)

他还写道:

我开始认为问题出在NSFetchedResultsController上,它始终停留在performFetch:当发生这些死锁时.大多数时候,由于要求它的部分名称,它会因为试图在对象中出错而被卡住.作为测试,我尝试重现FRC的功能并执行executeFetchRequest:然后遍历结果,询问每个对象的部分名称.这不会造成僵局.如果我离开FRC去执行performFetch:在我进行测试后它仍然会死锁.我99%确定FRC与嵌套上下文有同步问题.

问题:有人知道为什么会出现这个问题吗?你知道怎么解决吗?这是一个错误吗?

Mar*_*n R 34

我刚读过这篇SO帖子,其中fabrice truillot de chambrier建议目前不要使用嵌套的上下文.他提到了Core Data Growing Pains 这篇文章.

从那篇文章:

NSFetchedResultsController死锁

你永远不希望你的应用程序死锁.使用NSFetchedResultsController和嵌套上下文,这很容易做到.使用上述相同的UIManagedDocument设置,在将NSFetchedResultsController与主队列上下文一起使用时,在私有队列上下文中执行获取请求可能会死锁.如果你几乎在同一时间开始,几乎100%的一致性.NSFetchedResultsController可能正在获取它不应该的锁.据报道,即将发布的iOS版已经修复了这个问题.

雷达:// 11861499修正了即将发布的版本

这似乎准确描述了您的问题.

  • "据报道,即将推出的iOS版本也已修复此问题." - 真的,iOS 9现在,这个bug仍然在iOS中 (2认同)