美文网首页iOS开发总结crash
iOS 兼容多个有crash 收集机制的SDK

iOS 兼容多个有crash 收集机制的SDK

作者: Auditore | 来源:发表于2017-10-18 15:05 被阅读26次

    我们知道,如果一个APP内有多个第三方crash 收集SDK,那么很可能他们之间会有冲突,如果APP自身也有crash 收集机制,那么如何做兼容呢?

    1.UncaughtException
    如果同时有多方通过NSSetUncaughtExceptionHandler注册异常处理程序,和平的作法是:后注册者通过NSGetUncaughtExceptionHandler将先前别人注册的handler取出并备份,在自己handler处理完后自觉把别人的handler注册回去,规规矩矩的传递。不传递强行覆盖的后果是,在其之前注册过的日志收集服务写出的Crash日志就会因为取不到NSException而丢失Last Exception Backtrace等信息。(P.S. iOS系统自带的Crash Reporter不受影响)
    在开发测试阶段,可以利用 fishhook 框架去hookNSSetUncaughtExceptionHandler方法,这样就可以清晰的看到handler的传递流程断在哪里,快速定位污染环境者。不推荐利用调试器添加符号断点来检查,原因是一些Crash收集框架在调试状态下是不工作的。
    示例:

    static NSUncaughtExceptionHandler *previousUncaughtExceptionHandler;
    + (void)installExceptionHandler {   
     //将之前的注册的handler保存起来    previousUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();    NSSetUncaughtExceptionHandler(&LDAPMUncaughtExceptionHandler);
    }
    static void LDAPMUncaughtExceptionHandler(NSException *exception) {    
    // 获取堆栈,收集堆栈    
    // 这里做我们自己对exception的处理   
     // ······   
     // 处理完以后,调用前者的handler处理exception,让他们也有数据,如果不做处理,之前的注册的都将无法获取到exception   
     if (previousUncaughtExceptionHandler) {            
          previousUncaughtExceptionHandler(exception);   
        }
    }
    

    在开发测试阶段,可以利用 fishhook 框架去hook NSSetUncaughtExceptionHandler方法,这样就可以清晰的看到handler的传递流程断在哪里,快速定位污染环境者。不推荐利用调试器添加符号断点来检查,原因是一些Crash收集框架在调试状态下是不工作的。检测代码如下,

    static NSUncaughtExceptionHandler *g_vaildUncaughtExceptionHandler;​static void(*ori_NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler * );
    ​void my_NSSetUncaughtExceptionHandler( NSUncaughtExceptionHandler * handler)​{​    
    g_vaildUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();​   
     if (g_vaildUncaughtExceptionHandler != NULL) {​        
     NSLog(@"UncaughtExceptionHandler=%p",g_vaildUncaughtExceptionHandler);   
    } ​    
     ori_NSSetUncaughtExceptionHandler(handler);​    
     NSLog(@"%@",[NSThread callStackSymbols]);​   
     g_vaildUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();​ 
     NSLog(@"UncaughtExceptionHandler=%p",g_vaildUncaughtExceptionHandler);
    ​}
    

    2.Signal handler

    typedef void (*SignalHandler)(int signo, siginfo_t *info, void *context);​
    static SignalHandler previousSignalHandler = NULL;​
    + (void)installSignalHandler {    
    struct sigaction old_action;    
    sigaction(SIGABRT, NULL, &old_action);    
    //先保存之前旧的signal的handler    
    if (old_action.sa_flags & SA_SIGINFO) {        
    previousSignalHandler = old_action.sa_sigaction;   
    }    
    //注册我们自己的handler    
    LDAPMSignalRegister(SIGABRT);    
    // .......​
    }
    //注册signal handlerstatic 
    void LDAPMSignalRegister(int signal) {    
    struct sigaction action;    
    action.sa_sigaction = LDAPMSignalHandler;    
    action.sa_flags = SA_NODEFER | SA_SIGINFO;    sigemptyset(&action.sa_mask);    
    sigaction(signal, &action, 0);
    }
    static void LDAPMSignalHandler(int signal, siginfo_t* info, void* context) {    
    // 获取堆栈,收集堆栈   
    //........​    
    LDAPMClearSignalRigister();​    
    // 处理前者注册的 handler    
    if (previousSignalHandler) {        
    previousSignalHandler(signal, info, context);   
    }
    }
    

    相关文章

      网友评论

        本文标题:iOS 兼容多个有crash 收集机制的SDK

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