2013-08-20 21 views
11

私たちのアプリはpsynch_mutexwaitで半ランダムにハングしているようです。 これは、CoreDataに格納されたデータの束を更新するバックグラウンドプロセスに関連しているようですが、デッドロックを引き起こす原因を誰がロックしているかを完全に知ることはできませんでした。__psynch_mutexwaitでアプリケーションがハングする

以下は、lldbが私に与える完全なスタックトレースです。これは明らかに不完全であり、スレッド1の最後のフレームは偽です。私はその方法の中で数行前にブレークポイントを持っていましたが、決して打撃を受けませんでした。

どのロックが待機されているか把握する方法はありますか? (あるいは正しいスタックトレースを得ることさえできますか?)もちろん、たくさんのコードが含まれています。これは、ランダムなNSLogステートメントを大規模な作業にします。

(lldb) bt all 
* thread #1: tid = 0x2503, 0x39da20fc libsystem_kernel.dylib`__psynch_mutexwait + 24, stop reason = signal SIGSTOP 
    frame #0: 0x39da20fc libsystem_kernel.dylib`__psynch_mutexwait + 24 
    frame #1: 0x39ceb128 libsystem_c.dylib`pthread_mutex_lock + 392 
    frame #2: 0x00022068 OnDeck`-[AttendanceWorkoutsController buildTable](self=0x00000003, _cmd=0x00000000) + 508 at AttendanceWorkoutsController.m:100 

    thread #2: tid = 0x2803, 0x39d92648 libsystem_kernel.dylib`kevent64 + 24 
    frame #0: 0x39d92648 libsystem_kernel.dylib`kevent64 + 24 
    frame #1: 0x39ccb4f0 libdispatch.dylib`_dispatch_mgr_invoke + 796 

    thread #5: tid = 0x2b03, 0x39d91eb4 libsystem_kernel.dylib`mach_msg_trap + 20 
    frame #0: 0x39d91eb4 libsystem_kernel.dylib`mach_msg_trap + 20 
    frame #1: 0x39d9204c libsystem_kernel.dylib`mach_msg + 40 

    thread #6: tid = 0x242f, 0x39d91eb4 libsystem_kernel.dylib`mach_msg_trap + 20 
    frame #0: 0x39d91eb4 libsystem_kernel.dylib`mach_msg_trap + 20 
    frame #1: 0x39d9204c libsystem_kernel.dylib`mach_msg + 40 

    thread #7: tid = 0x2c03, 0x39da2594 libsystem_kernel.dylib`select$DARWIN_EXTSN + 20 
    frame #0: 0x39da2594 libsystem_kernel.dylib`select$DARWIN_EXTSN + 20 
    frame #1: 0x31bff1f6 CoreFoundation`__CFSocketManager + 678 

    thread #8: tid = 0x2d03, 0x39da2d98 libsystem_kernel.dylib`__workq_kernreturn + 8 
    frame #0: 0x39da2d98 libsystem_kernel.dylib`__workq_kernreturn + 8 
    frame #1: 0x39cf0cfa libsystem_c.dylib`_pthread_workq_return + 18 
(lldb) 

答えて

2

これは、別のコンテキスト(別のスレッド上で)で関連エンティティが変更ではなく、まだ永続化されたときに見られました。

シナリオ:

A --> B

バグのBに別のスレッド上で、別のコンテキストでは、保留中の変更をしていました。バグにより、Bが保存またはロールバックされる代わりにハングアップすることになりました。 Aを現在のコンテキスト/スレッドに保存しようとすると、他のスレッドがロックを解放するまで待つことになります(B)。

トラブルシューティングに成功したのは、すべての保留中のエンティティを一覧表示し、ブロックされたスレッドのものと比較することだけでした。しばらく時間がかかった:(

私はまだデータベースとエンティティ上のすべてのロックを一覧表示し、何かを探しています。

12

いくつかの人がコードを見て、長い複雑なコードパスをトレース持つことによって、私たちは何を見つけます犯人されているように見えます。バックグラウンドスレッドで実行されている 一つの方法は、見つけて、いくつかのコアデータオブジェクトを使用して、メイン・スレッドのコンテキストを使用していた。

IOSが有用スタックトレースを与える場合は確かにたくさん助けただろう。

+2

してみてください。このような状況のために導入されました。 – Mazyod

2

これは通常、コアにアクセスしようとすると発生します主スレッドコンテキストまたはを使用して、バックグラウンドスレッド上のデータオブジェクトは、異なるスレッド(バックグラウンドまたはメイン)上で同時に同じ管理対象オブジェクトコンテキストを使用します。詳細はCore Data concurrency rulesをご覧ください。

両方のケースを避けるため、主なルールは、各スレッドが独自の管理対象オブジェクトコンテキストを持ち、そのコンテキストを使用する場所で正確に初期化する必要があるということです。例えば

:アサーションをトリガするマルチスレッドコアデータを有効

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 

    // 
    // Prepare your background core data context 
    // 

    if (self.privateContext == nil) 
    { 
     self.privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
     [self.privateContext setParentContext: - main managed object context - ]; 
     [self.privateContext setUndoManager:nil]; // this context should not manage undo actions. 
    } 

    // 
    // Do any Core Data requests using this thread-save context 
    // 

    . 
    . 
    . 

}); 
関連する問題