Contextos de objetos gerenciados aninhados de dados principais e conflitos frequentes / congelamentos

Eu tenho um problema que é quase idêntico ao problema descrito por essa pessoa aqui, mas ela não foi respondida:

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

Aqui está o problema:

Eu tenho uma configuração de MOC pai com NSPrivateQueueConcurrencyType e um conjunto de coordenador de armazenamento persistente, ele tem uma configuração de MOC filho com NSMainQueueConcurrencyType. A ideia de ser a maior parte do trabalho longo e difícil de salvar pode ser feita no MOC privado, liberando o thread principal de bloquear a interface do usuário. Infelizmente, pareço estar se deparando com algumas situações que causam deadlocks.

Se o filho MOC (no thread principal) estiver executando uma busca com NSFetchedResultsController, o contexto pai será enviado como um -executeFetchRequest: ele poderá criar um deadlock. Ambas as operações são feitas dentro do contexto de um performBlock: para seus respectivos MOCs, embora os docs pareçam indicar que o uso de um tipo de simultaneidade do thread principal MOC no thread principal sem performBlock: está bem.

Parece que a fila particular está aguardando no bloqueio de PSCs que o contexto filho no thread principal já foi bloqueado. Parece que o contexto filho (enquanto segura o bloqueio de PSCs) está tentando dispatch_sync para o contexto pai e, portanto, ambos estão esperando um pelo outro.

PriveQueue -> MainQueue é uma configuração suportada? Parece que a maioria das pessoas ainda tem o contexto pai no thread principal.

O tópico principal é assim:

> #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

a pilha da fila particular se parece com isso:

#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 ()

Ele também escreve isso:

Eu estou começando a pensar que o problema é com NSFetchedResultsController que está sempre preso em performFetch: quando esses deadlocks ocorrem. Na maior parte do tempo, ele ficará preso tentando causar falha em um objeto, como resultado de pedir o nome da seção. Como teste, tentei reproduzir o que o FRC faz e executei o executeFetchRequest: e depois iterar pelos resultados, pedindo a cada objeto o seu nome de seção. E isso não causa um impasse. Se eu deixar o FRC para fazer performFetch: depois que eu fizer o meu teste, ele ainda estará travado. Tenho 99% de certeza de que o FRC tem um problema de sincronização com contextos aninhados.

Pergunta: Alguém sabe por que esse problema ocorre? Você sabe como resolver isso? Isso é um inseto?

questionAnswers(7)

yourAnswerToTheQuestion