美文网首页
iOS Crash的捕获知识

iOS Crash的捕获知识

作者: oncezou | 来源:发表于2018-12-14 13:22 被阅读20次

    1. crash的类型

    crash一般产生自 iOS 的微内核 Mach,然后在 BSD 层转换成 UNIX SIGABRT 信号,以标准 POSIX 信号的形式提供给用户。NSException 是使用者在处理 App 逻辑时,用编程的方法抛出。

    • Mach 异常:EXC_CRASH
    • UNIX 信号:SIGABRT
    • NSException 异常:应用层,通过 NSUncaughtExceptionHandler 捕获

    2. crash的捕获的方式

    • Mach 异常捕获。如果想要做mach 异常捕获,需要注册一个异常端口,这个异常端口会对当前任务的所有线程有效,如果想要针对单个线程,可以通过 thread_set_exception_ports注册自己的异常端口,发生异常时,首先会将异常抛给线程的异常端口,然后尝试抛给任务的异常端口,当我们捕获异常时,就可以做一些自己的工作,比如,当前堆栈收集等。

    • Unix 信号捕获。对于Mach 异常,操作系统会将其转换为对应的 Unix信号,所以如果你对Mach不熟悉的话,也可以通过注册signalHandler的方式来做信号异常。

       signal(SIGABRT, SignalExceptionHandler)   
       signal(SIGSEGV, SignalExceptionHandler)
       signal(SIGBUS, SignalExceptionHandler)
       signal(SIGTRAP, SignalExceptionHandler)
       signal(SIGILL, SignalExceptionHandler)
      
    • NSException 捕获
      对于NSException异常,也比较容易处理,通过注册NSUncaughtExceptionHandler捕获异常信息即可,将拿到的NSException细节写入Crash日志,上传到后台做数据分析

    NSSetUncaughtExceptionHandler(UncaughtExceptionHandler)
    

    多个 Crash 收集框架存在时,往往会存在冲突。
    不管是对于 Signal 捕获还是 NSException 捕获都会存在 handler 覆盖的问题,正确的做法应该是先判断是否有前者已经注册了 handler,如果有则应该把这个 handler 保存下来,在自己处理完自己的 handler 之后,再把这个 handler 抛出去,供前面的注册者处理。

    资料: 漫谈iOS Crash收集框架

    4.堆栈符号解析

    堆栈符号化还原有三种常见的方法:

    • symbolicatecrash
    • mac 下的 atos 工具
    • 通过 dSYM 文件提取地址和符号的对应关系,进行符号还原
    // 未符号化前
    Thread 0 name:  Dispatch queue: com.apple.main-thread
    Thread 0 Crashed:
    0   libobjc.A.dylib                 0x000000018b816f30 0x18b7fc000 + 110384 (objc_msgSend + 16)
    1   UIKit                           0x0000000192e0a79c 0x192c05000 + 2119580 (<redacted> + 72)
    2   UIKit                           0x0000000192c4db48 0x192c05000 + 297800 (<redacted> + 312)
    3   UIKit                           0x0000000192c4d988 0x192c05000 + 297352 (<redacted> + 160)
    4   QuartzCore                      0x00000001900d6404 0x18ffc5000 + 1119236 (<redacted> + 260)
    
    // 符号化后
    Thread 0 name:  Dispatch queue: com.apple.main-thread
    Thread 0 Crashed:
    0   libobjc.A.dylib                 0x000000018b816f30 objc_msgSend + 16
    1   UIKit                           0x0000000192e0a79c -[UISearchDisplayController _sendDelegateDidBeginDidEndSearch] + 72
    2   UIKit                           0x0000000192c4db48 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
    3   UIKit                           0x0000000192c4d988 -[UIViewAnimationState animationDidStop:finished:] + 160
    4   QuartzCore                      0x00000001900d6404 CA::Layer::run_animation_callbacks(void*) + 260
    

    Xcode的Organizer内置了symbolicatecrash,所以我们才可以直接看到符号化的崩溃堆栈日志

    资料:实战iOS崩溃堆栈的符号化解析
    轻量级的堆栈采集框架:BSBacktraceLogger

    5.启动连续闪退

    • 闪退原因

        1. 数据库损坏:在日常使用如异常退出、断电,或者错误的操作(参考:sqlite corruption causes)。
        2. 文件损坏:处理文件时如果没有 @try...catch,损坏文件会抛出 NSException 导致 crash
        3. 网络返回数据处理异常:比如预期返回数组,但实际返回了字典,对字典对象执行 -objectAtIndex 方法会产生 crash: unknow selector send to object;,或返回破损的 Tar 包,在解压失败导致 crash。
        4. 代码 bug:当必 crash 的代码出现在启动关键路径中,就会导致连续闪退。
        5. 针对 1,可以通过工具修复数据库,或者删除 DB。针对2,可以删除文件来进行修复。对于 3 和 4,我们需要具体地分析 crash 案例,通过 JSPatch 来进行修复。
      
    • 计时器方法

      1. 维护一个计数变量,用于表示连续闪退的次数
      2. 在启动 application:didFinishLaunchingWithOptions: 后使计数加一
      3. 接着使用 dispatch_after 方法在 5s 后清零计数,如果 App 活不过 5 秒计数就不会被清零
      4. 如果发现计数变量 > n,表明 App 连续 n 次连续闪退,启动保护流程,重置计数。
      5. 当保护流程完成后,进入 App 正常启动流程
      
    • 时间数组比对

    在本地保存一个 App 每次启动时间、闪退时间、手动关闭时间的时间数组,然后在 App 启动时根据分析各个时间戳判断是否存在连续闪退(当闪退时间减去启动时间小于阈值 5 秒时,则认为是启动闪退)

    1. App 每次启动时,记录当前时间 launchTs,写入时间数组;
    2. App 每次启动时,通过 crash 采集库,获取上次 crash report 的时间戳 crashTs,写入时间数组;
    3. App 在接收到 UIApplicationWillTerminateNotification 通知时,记录当前时间戳 terminateTs,写入时间数组。注意,之所以要记录 terminateTs,是为了排除一种特殊情况,即用户启动 App 之后立即手动 kill app。
    

    资料:
    iOS 启动连续闪退保护方案
    连续启动 crash 自修复技术实现与原理解析
    两种 App 启动连续闪退检测策略

    6.crash收集方式

    • 第三方平台:Fabric、友盟、腾讯 Bugly等,数据会上传到这些平台
    • 第三方工具: KSCrash、plcrashreporter等,可自行处理收集的crash(发送到邮箱/上传自己服务器)
    • 自定义捕获+堆栈符号化

    相关文章

      网友评论

          本文标题:iOS Crash的捕获知识

          本文链接:https://www.haomeiwen.com/subject/ndxghqtx.html