10

更新 2: MOC の割り当て解除と保存を同期する回避策を見つけました。更新されたプロジェクトを参照してください。 https://github.com/shuningzhou/MOCDadLock.git

注: より積極的に失敗させました。実際のデバイスで実行しないでください。

更新:この問題を示すサンプル プロジェクト。 https://github.com/shuningzhou/MOCDadLock.git

XCode 6.2: 再現できません。

XCode 6.3: 再現可能。

XCode 6.4 ベータ版: 再現可能。

==========================問題====================== =========

OSSpinLockLockSlowXCode 6.3 にアップグレードした後、アプリがランダムにスタックしました。私たちのプロジェクトでは、 と を使用NSOperationNSOperationQueueてサーバーからデータをフェッチし、コア データを使用してデータを永続化しました。

この問題は、これまで発生したことはありません。スタック トレースから、コードによって呼び出しが行われていないことがわかります。これのデバッグをどこから開始すればよいかわかりません。誰かがガイダンスを提供できますか?

前もって感謝します!

スタックトレースを見てください ここに画像の説明を入力

ここに画像の説明を入力

編集:

を使用AFNetworkingしており、 のNSOperationsサブクラスですAFHTTPRequestOperation。いくつかのカスタム プロパティを追加し、メソッドをオーバーライドしました-(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];
}

についてCore Dataは、thread-confinementパターンに従っています。managed object contextスレッドごとに分離されており、コンテキストは static を共有していますpersistent store coordinator

編集2:

詳細: システムが複数のスレッドを同時に終了すると、この問題が発生することがわかりました。管理オブジェクト コンテキストをスレッド ディクショナリに格納し、スレッドが終了すると解放されます。

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

CPU 使用率は約 20% です。 ここに画像の説明を入力 ここに画像の説明を入力

4

2 に答える 2

13

私はまさにこの問題を経験しています。スタック トレースによると、_OSSpinLockLockSlow で多数のスレッドが停止しています。

スピンロックが連鎖したライブロック状態のようです。いくつかのネットワーク スレッドとコア データを含みます。しかし、Rob が指摘したように、ライブロックの症状には高い CPU 使用率が含まれるはずです (スピンロックはすべて無限に回転しています)。私の場合(そしてあなたの場合)はそうではありません.CPU使用率は低く、シミュレータの「使用率」は20%、アクティビティモニタのシミュレータ全体は0.6%です-デッドロックかもしれません;-)

あなたと同じように、私はスレッド制限パターン、スレッドごとに個別の管理対象オブジェクト コンテキスト、単一の永続ストアを使用しています。

ハングは常に一連のスレッドの割り当て解除に続くように見えるというあなたの観察に従って、私はその動作をチェックし、それが事実であることを確認できました.

これにより、なぜこれほど多くのスレッドがアクティブになっているのか疑問に思いました。同時バックグラウンド キューで gcd を使用していたことが判明しました。

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

このスニペットは、ネットワーク/JSON 解析コードの一部です。「classForID」がメイン スレッドでわずかな UI ジッターを引き起こしていたので、バックグラウンドにしました。

事実上、並行バックグラウンド キューは、存続期間の短いスレッドを大量に吐き出していました。これはまったく不要でした。単一のシリアル キューとしてリファクタリングすると、スレッドの過剰が修正され、スピンロックの問題が解消されました。最後に、クラスを取得する必要がまったくないことに気付きました。そのため、このコードは削除されました。

問題は修正されましたが、これが 8.3 で突然問題になる理由についての説明はありません

この質問でも同じ問題に触れているのではないかと思います (Cocoalumberjack が責任を負いますが):
syscall_thread_switch iOS 8.3 race - CocoaLumberjack bug? これをデバッグする方法は?

..そして、この Cocoalumberjack バグレポートで
https://github.com/CocoaLumberjack/CocoaLumberjack/issues/494

私も CocoaLumberjack を使用していますが、問題のあるスレッドのいずれにも含まれていないため、それはニシンだと思います。根本的な原因は、過剰なスレッド作成のようです。

XCode にテザリングされている場合、シミュレーターとデバイスで問題を確認しましたが、XCode とは独立して実行している場合は経験していません。iOS 8.3 / XCode 6.3.1 では初めてです

本当の答えではなく、この奇妙な問題に対する私自身の回避策の日記ですが、役に立つかもしれません。

于 2015-05-19T18:18:08.660 に答える
1

質問がまだ実際の場合 - これは iOS のバグです: OpenRadar クラッシュ レポート
また、このブログ投稿が役立つ場合があります:ブログ投稿

アプリでこれを修正するには、OSSpinLocks を別のものに置き換える必要があると思います。

Unity3d ゲームでこのバグに遭遇しました。ほとんどのネイティブ iOS コードにアクセスできないため、アプリではまだこれを修正していません (C# でゲームを作成し、多くのサードパーティのネイティブ プラグインを使用しています)。したがって、OSSpinLock の置き換えについて具体的なことをお勧めすることはできません。私の英語でごめんなさい。

更新
多くの Apple フレームワークとライブラリは内部で OSSpinLock を使用しているため、この問題に遭遇するために明示的に使用する必要はありません。

于 2016-01-26T09:53:55.337 に答える