在iOS上侦听崩溃

时间:2019-02-12 11:12:31

标签: ios swift logging

说明

我想捕获iOS应用程序中发生的所有异常并将它们记录到文件中,并最终将它们发送到该应用程序使用的后端服务器。

我一直在阅读有关此主题的内容,并发现了设备发送和处理的信号的用法,但不确定是否会违反App Store审查指南,否则可能会带来其他问题。

我已将以下内容添加到AppDelegate

NSSetUncaughtExceptionHandler { (exception) in  
    log.error(exception)  
}  

signal(SIGABRT) { s in  
    log.error(Thread.callStackSymbols.prettified())  
    exit(s)  
}  

signal(SIGILL) { s in  
    log.error(Thread.callStackSymbols.prettified())  
    exit(s)  
}  

signal(SIGSEGV) { s in  
    log.error(Thread.callStackSymbols.prettified())  
    exit(s)  
}

问题

  • 这是一种很好的方法吗?
  • 由于使用exit()
  • ,它是否会违反App Store审核指南
  • 使用kill(getpid(), SIGKILL)代替exit()更好吗?

资源

1 个答案:

答案 0 :(得分:8)

此处是以前的Crashlytics iOS SDK维护者。

您上面编写的代码确实存在许多技术问题。

首先,实际上很少有被定义为可以在信号处理程序中安全调用的函数。 man sigaction列出了它们。您编写的代码不是信号安全的,有时会死锁。这一切都取决于崩溃的线程当时在做什么。

第二个是您试图在处理程序之后退出程序。您必须记住,信号/异常处理程序是进程范围内的资源,您可能不是唯一使用它们的人。您必须保存预先存在的处理程序,然后在处理后还原它们。否则,可能会对应用程序可能正在使用的其他系统产生负面影响。如您目前所写,即使Apple自己的崩溃报告器也不会被调用。但是,也许您想要这种行为。

第三,您没有捕获所有线程堆栈。这是崩溃报告的关键信息,但增加了很多复杂性。

第四,信号实际上不是最低级别的错误系统。不要与运行时异常(即NSException混淆)马赫异常是用于在iOS上实现信号的基本机制。它们是一个更强大的系统,但也要复杂得多。信号具有很多陷阱和局限性,可以避免许多异常。

这些只是我想到的问题。崩溃报告是一项棘手的业务。但是,我不希望您认为这是魔术,当然不是。您可以构建一个有效的系统。

我想指出的一件事是,崩溃报告程序没有提供关于失败的反馈。因此,您可能会构建出25%的时间都可以工作的东西,并且由于只看到有效的报告,您会认为“嘿,这很好!”。 Crashlytics必须付出多年的努力才能找出失败的原因并设法减轻它们。如果您对这一切都感兴趣,则可以查看我对Crashlytics系统所做的talk

更新

那么,如果发布此代码会发生什么?好吧,有时候您会得到有用的报告。有时,您的崩溃处理代码本身也会崩溃,这将导致无限循环。有时您的代码将陷入僵局,并有效地挂起您的应用程序。

Apple公开了exit公共API(无论好坏),因此您绝对可以使用它。

我建议您仅出于学习目的而继续这条路。如果您有一个真正的应用程序在乎,那么我认为集成一个现有的开源报告系统并将其指向您控制的后端服务器将更具责任感。没有第三方,也没有必要担心弊大于利。