2015-05-15 12 views
10

Aggiornamento 2: Ho trovato una soluzione alternativa per sincronizzare MOC deallocating e saving. Si prega di consultare il progetto aggiornato. https://github.com/shuningzhou/MOCDeadLock.gitApplication sticks on OSSpinLockLockSlow

Nota: l'ho fatto fallire in modo più aggressivo. Non eseguirlo su un dispositivo reale!

Aggiornamento: Un progetto di esempio per dimostrare questo problema. https://github.com/shuningzhou/MOCDeadLock.git

XCode 6.2: impossibile riprodurre.

XCode 6.3: Riproducibile.

XCode 6.4 beta: Riproducibile.

========================== Il problema ================ ===============

Dopo l'aggiornamento a XCode 6.3, la nostra app è stata bloccata in modo casuale su OSSpinLockLockSlow. Nel nostro progetto, abbiamo utilizzato NSOperation e NSOperationQueue per recuperare i dati dal nostro server e utilizzato i dati principali per la persistenza dei dati.

Questo problema non è mai accaduto prima! È possibile vedere dallo stack trace che nessuna chiamata viene effettuata dal nostro codice. Non sono sicuro da dove iniziare il debug di questo. Qualcuno potrebbe fornire una guida?

Grazie in anticipo!

prega di consultare la traccia dello stack enter image description here

enter image description here

Edit:

Stiamo usando AFNetworking e la nostra NSOperations sono sottoclassi di AFHTTPRequestOperation. Abbiamo aggiunto alcune proprietà personalizzate e sovrascritto il metodo -(void)start:

- (void)start; 
{ 
    //unrelated code... 

    NSString *completionQueueID = [NSString uuid]; 
    const char *cString = [completionQueueID cStringUsingEncoding:NSASCIIStringEncoding]; 
    self.completionQueue = dispatch_queue_create(cString, DISPATCH_QUEUE_SERIAL); 

    //unrelated code.... 

    [super start]; 
} 

Per Core Data, stiamo seguendo il modello thread-confinement. Abbiamo separato managed object context per ogni thread e i contesti condividono un valore statico persistent store coordinator.

Edit 2:

Maggiori informazioni: ho trovato che questo problema si verifica quando il sistema esce più thread contemporaneamente. Archiviamo il contesto oggetto gestito nel dizionario del thread e vengono rilasciati all'uscita dai thread.

[[[NSThread currentThread] threadDictionary] setObject:dataManager forKey:@"IHDataManager"]; 

L'utilizzo della CPU è di circa il 20%. enter image description here enter image description here

+2

Si prega di pubblicare il codice relativo a 'NSOperation'. – SevenBits

+1

Avete un gestore di segnale nel vostro sistema, in particolare un gestore di crash? Dai un'occhiata ai tuoi thread per qualsiasi riferimento a '_sigtramp'. (Nota che puoi copiare tracce di stack con Cmd-C, non devi fare screenshot.) Suppongo che l'utilizzo della CPU diventi molto alto (forse accende i fan)? –

+0

@SevenBits si prega di vedere la domanda modificata –

risposta

13

Ho riscontrato proprio questo problema. Come per la traccia dello stack, ho bloccato un certo numero di thread con _OSSpinLockLockSlow.

E appare per essere una situazione di tensione con gli spinlock incatenati insieme. Compresi alcuni thread di rete e dati di base. Ma, come ha sottolineato Rob, i sintomi del livelock dovrebbero includere un utilizzo elevato della CPU (gli spinlock girano all'infinito). Nel mio caso (e nel tuo) questo non è il caso, l'utilizzo della CPU è basso - il simulatore 'percento usato' 20%, il simulatore nel monitoraggio dell'attività 0,6% - quindi forse è un deadlock ;-)

Come te, Sto usando un modello di confinamento del thread, contesto dell'oggetto gestito separato per thread, singolo archivio permanente.

In seguito alla tua osservazione che il blocco sembra sempre seguire deallocing di un mucchio di thread, ho controllato tale comportamento e posso confermare che è il caso.

Questo mi ha chiesto perché Ho avuto così tanti thread attivi. Si è scoperto che stavo usando GCD con una coda di sfondo concomitante:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0),^{ 
     modelClass = [WNManagedObject classForID:mongoID]; 
     dispatch_async(dispatch_get_main_queue(),^{ 
     ... 
     }); 
     }); 

Questo frammento è parte di un codice di analisi di rete/JSON. 'classForID' causava lievi jitter sul thread principale, quindi l'ho preso in considerazione.

In effetti la coda di sfondo concomitante stava sputando un intero gruppo di thread di breve durata. Questo era completamente inutile. Refactoring come una singola coda seriale ha corretto gli eccessi di thread, eliminando il problema spinlock. Alla fine ho capito che non avevo bisogno di ottenere la classe, quindi questo codice è stato da allora esorcizzato.

problema risolto, ma nessuna spiegazione sul motivo per cui questo dovrebbe improvvisamente diventare un problema con 8,3

Ho il sospetto che lo stesso problema è toccato a questa domanda (anche se Cocoalumberjack ottiene la colpa lì):
syscall_thread_switch iOS 8.3 race - CocoaLumberjack bug? how to debug this?

..e in questo bug report Cocoalumberjack
https://github.com/CocoaLumberjack/CocoaLumberjack/issues/494

sono anche utilizzando CocoaLumberjack ma non a rendere rilevante in nessuna delle discussioni problema, così ho t hink che è un'aringa rossa. La causa sottostante sembra essere la creazione di thread in eccesso.

Ho visto il problema nel simulatore e sui dispositivi quando collegato a XCode, ma non l'ho provato nell'esecuzione indipendentemente da XCode. Per me è una novità per iOS 8.3/XCode 6.3.1

Non proprio una risposta, più un diario del mio modo di risolvere questo strano problema, ma forse lo troverai utile.

+0

Grazie mille per la risposta! Up votato di sicuro. –

+0

Sto utilizzando anche CocoaLumberJack e ho letto le due domande correlate prima di pubblicare il mio. Penso che CocoalumberJack non sia correlato. –

+0

Spesso vedo questo problema quando utilizzo AsyncImageView per visualizzare molte foto. – wolfrevo

1

Se questione è ancora attuale - questo è un bug in iOS: OpenRadar crash report
Inoltre si possono trovare questo post utile: blog post

penso che si dovrebbe sostituire OSSpinLocks con qualcos'altro per risolvere questo problema nella vostra applicazione.

Abbiamo riscontrato questo errore nel nostro gioco Unity3d. Non abbiamo ancora risolto questo problema nella nostra app perché non abbiamo accesso alla maggior parte del codice iOS nativo (scriviamo il nostro gioco su C# e utilizziamo molti plug-in nativi di terze parti). Quindi non posso raccomandarti qualcosa di concreto sulla sostituzione di OSSpinLock. Mi scusi per il mio inglese.

Aggiornamento
Molti quadri di Apple e librerie utilizza OSSpinLock internamente, quindi non avete bisogno di usarlo esplicitamente per eseguire in questo problema.