拦截iOS上的崩溃 描述

拦截iOS上的崩溃 描述,ios,swift,logging,Ios,Swift,Logging,我希望捕获iOS应用程序中发生的所有异常,并将它们记录到文件中,最终将它们发送到应用程序使用的后端服务器 我一直在阅读关于这个主题的文章,发现了设备发送的信号的用法,并对其进行了处理,但我不确定这是否会违反应用商店审查指南,或者可能会带来其他问题 我已将以下内容添加到AppDelegate: NSSetUncaughtExceptionHandler { (exception) in log.error(exception) } signal(SIGABRT) { s in

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

我一直在阅读关于这个主题的文章,发现了设备发送的信号的用法,并对其进行了处理,但我不确定这是否会违反应用商店审查指南,或者可能会带来其他问题

我已将以下内容添加到
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()
  • 使用
    kill(getpid(),SIGKILL)
    而不是
    exit()
    更好吗

资源


这里是Crashlytics iOS SDK的前维护者

上面编写的代码确实存在一些技术问题

第一个问题是,在信号处理程序中,实际上很少有被定义为可以安全调用的函数<代码>手动操作列出了它们。您编写的代码不是信号安全的,有时会死锁。这一切都将取决于崩溃线程当时在做什么

第二种情况是,您正试图在处理程序之后退出程序。您必须记住,信号/异常处理程序是进程范围的资源,您可能不是唯一使用它们的人。您必须保存预先存在的处理程序,然后在处理后恢复它们。否则,您可能会对应用程序可能正在使用的其他系统造成负面影响。正如您目前所写的,即使是苹果自己的crash reporter也不会被调用。但是,也许你想要这种行为

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

第四,信号实际上不是最低级别的误差系统。不要与运行时异常混淆(即
NSException
mach异常是用于在iOS上实现信号的底层机制。它们是一个更加健壮的系统,但也更加复杂。信号有很多陷阱和限制,马赫数异常会绕过这些陷阱和限制

这些只是我脑海中浮现的问题。事故报告是一项棘手的工作。但是,我不想让你认为这是魔法,当然不是。你可以建立一个有效的系统

我想指出的一件事是,事故记者不会给你任何关于失败的反馈。因此,您可能会构建一个在25%的时间内都能工作的东西,并且因为您只看到有效的报告,所以您会认为“嘿,这太好了!”。Crashlytics公司多年来一直在努力找出故障原因,并试图缓解故障。如果你对这些都感兴趣,你可以看看我做的关于Crashlytics系统的文章

更新:

那么,如果你发送这个代码会发生什么?嗯,有时候你会得到有用的报告。有时,崩溃处理代码本身会崩溃,这将导致无限循环。有时你的代码会死锁,并有效地挂起你的应用程序

苹果已经发布了
exit
公共API(无论好坏),所以你完全可以按照规则使用它

我建议继续沿着这条路走下去,只是为了学习。如果你有一个真正关心的应用程序,我认为集成现有的开源报告系统并将其指向你控制的后端服务器会更负责任。没有第三方,也不必担心弊大于利。

结论 可以创建自定义崩溃报告器,但绝对不建议这样做,因为在后台发生的很多事情很容易被忘记,并且可能会引入许多未定义的行为。即使使用第三方框架也会很麻烦,但这通常是更好的方法

感谢大家提供有关此主题的信息

对问题的答复 这是个好办法吗,还有其他办法吗? 我在原始问题中提到的方法将对苹果自己的crash reporter产生影响,由于信号处理不当,它引入了未定义的行为。UNIX信号并没有覆盖所有错误和API处理工作,而是使用异步信号安全函数。苹果的crash reporter使用的马赫异常处理是更好的选择,但它更复杂

使用
exit()
会打破苹果应用商店的审查吗? 否。
exit()
的使用与应用程序的正常运行更相关。若应用程序正在崩溃,调用
exit()
并不是问题

使用kill(getpid(),SIGKILL)而不是exit()更好吗? 引用爱斯基摩人的话:

你不能叫出口。这样做有两个问题:

退出不是异步信号安全的。事实上,exit可以运行任意代码 通过在atexit注册的处理程序。如果要退出该进程, 呼叫退出

退出流程无论如何都是个坏主意,因为它会 防止Apple crash reporter运行或使其记录 不正确的状态(信号处理程序的状态,而不是 崩溃线程的状态)

更好的解决方案是注销信号处理程序(将其设置为 然后返回


其他详细信息(完整上下文) 由于我将这些问题交叉发布到了,并从著名的爱斯基摩人那里得到了非常长的描述性答案,我想与任何决定走与我相同的道路并开始研究这种方法的人分享

引用爱斯基摩人的话

在我们开始之前,我想让你看看我闪亮的新衣服。我一直想写这篇文章 有一段时间,你的问题给了我一个很好的理由来分配 时间

你写道:

我有一个要求,要捕获所有在 iOS应用程序