我有一个问题与此人在此处描述的问题几乎相同,但尚未得到解答:
这是问题所在:
我有一个带有 NSPrivateQueueConcurrencyType 的父 MOC 设置和一个持久存储协调器集,它有一个带有 NSMainQueueConcurrencyType 的子 MOC 设置。这个想法是大部分长期的努力和保存可以在私有 MOC 上完成,从而将主线程从阻塞 UI 中释放出来。不幸的是,我似乎遇到了几种导致死锁的情况。
如果子 MOC(在主线程上)正在使用 NSFetchedResultsController 执行获取,则向父上下文发送一个 -executeFetchRequest:它可以创建死锁。这两个操作都是在 performBlock: 的上下文中完成的,尽管文档似乎表明在没有 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
the private queue stack looks like this:
#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 ()
He also writes this:
I'm starting to think the problem is with NSFetchedResultsController which is always stuck at performFetch: when these deadlocks occur. Most of the time it will be stuck trying to fault in an object as a result of asking for it's section name. As a test I tried to reproduce what the FRC does and performed the executeFetchRequest: and then iterated through the results asking each object for it's section name. And this doesn't cause a deadlock. If I leave the FRC to do performFetch: after I do my test it will still deadlock there. I'm 99% sure that the FRC has a synchronization problem with nested contexts.
Question: Does anybody know why this problem occurs? Do you know how to solve it? Is this a bug?