可以在PLCrashReporter信号回调中使用Core Foundation吗?

时间:2015-05-26 12:47:12

标签: ios plcrashreporter

我在我的iOS项目中使用PLCrashReporter并且我很好奇,是否可以在我的自定义崩溃回调中使用Core Foundation代码。处理我需求的是CFPreferences.Here是我创建的代码的一部分:

void LMCrashCallback(siginfo_t* info, ucontext_t* uap, void* context) {
  CFStringRef networkStatusOnCrash;
  networkStatusOnCrash = (CFStringRef)CFPreferencesCopyAppValue(networkStatusKey, kCFPreferencesCurrentApplication);
  CFStringRef additionalInfo = CFStringCreateWithFormat(
              NULL, NULL, CFSTR( "Additional Crash Properties:[Internet: %@]", networkStatusOnCrash);
  CFPreferencesSetAppValue(additionalInfoKey, additionalInfo,
                           kCFPreferencesCurrentApplication);
  CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
}

我的目标是收集一些系统信息,就在应用程序崩溃的时候,例如Internet连接类型。

我知道由于异步安全函数而创建自己的崩溃回调并不是一个好主意,但这可能有所帮助。

另外还有其他选择:有没有办法以某种方式扩展PLCrashReportSystemInfo类?

1 个答案:

答案 0 :(得分:3)

这非常危险。特别是对CFStringCreateWithFormat的调用分配内存。在崩溃处理程序中间分配内存会导致电池耗尽死锁(是的;有那个错误...)例如,如果你在free()(这不是一个不常见的崩溃地点)的中间,你可能已经在堆上持有一个螺旋锁。当你调用malloc获取一些内存时,你可能会再次自动锁定堆并在紧密循环中死锁。堆需要经常锁定,并且在如此短的时间内不会使用阻塞锁。它相当于while (locked) {}

您似乎只是在阅读偏好并将其复制到另一个偏好。在崩溃处理程序中没有理由这样做。只需在启动期间检查hasPendingCrashReport(我假设您已经做过),然后阅读密钥。我不清楚networkStatusKey是什么,但是当你重新开始时它应该仍然存在。

如果由于任何原因它很早就被修改(在您致电hasPendingCrashReport之前),您可以在启动应用之前在main()中抓取它。或者您可以使用+load方法获取它,甚至可以更早地调用它。