10

更新 2:我找到了一种解决方法,即同步 MOC 释放和保存。请查看更新的项目。 https://github.com/shuningzhou/MOCDeadLock.git

注意:我让它更积极地失败。不要在真实设备上运行它!

更新:演示此问题的示例项目。 https://github.com/shuningzhou/MOCDeadLock.git

XCode 6.2:无法重现。

XCode 6.3:可重现。

XCode 6.4 beta:可重现。

===========================问题====================== =========

OSSpinLockLockSlow我们的应用在升级到 XCode 6.3 后随机卡住。在我们的项目中,我们使用NSOperationandNSOperationQueue从我们的服务器获取数据,并使用 Core Data 进行数据持久化。

这个问题以前从来没有发生过!您可以从堆栈跟踪中看到我们的代码没有进行任何调用。我不确定从哪里开始调试。有人可以提供一些指导吗?

先感谢您!

请查看堆栈跟踪 在此处输入图像描述

在此处输入图像描述

编辑:

我们正在使用AFNetworking并且我们NSOperationsAFHTTPRequestOperation. 我们添加了一些自定义属性并覆盖了方法-(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# 编写游戏并且使用了很多 3-rd 方原生插件)。所以我不能向你推荐一些关于替换 OSSpinLock 的具体内容。对不起我的英语不好。

更新
许多 Apple 框架和库在内部使用 OSSpinLock,因此您无需明确使用它即可遇到此问题。

于 2016-01-26T09:53:55.337 回答