美文网首页
异常捕获上传服务器

异常捕获上传服务器

作者: 南京小伙 | 来源:发表于2017-09-11 11:46 被阅读0次

    要接入上海分部的自己的性能统计和事件统计的 sdk,在接入之前自己了解下。看到了一套捕获异常的代码。

    对于异常分为了两种,一种是系统抛出的 Exception 异常,iOS 提供了 NSSetUncaughtExceptionHandler 函数来进行捕获。对于另一种 Signal 异常需要自己单独捕获处理,最终还是转成 Exception 异常上传至服务器。

    Signal 信号类型:

    SIGABRT--程序中止命令中止信号

    SIGALRM--程序超时信号

    SIGFPE--程序浮点异常信号

    SIGILL--程序非法指令信号

    SIGHUP--程序终端中止信号

    SIGINT--程序键盘中断信号

    SIGKILL--程序结束接收中止信号

    SIGTERM--程序kill中止信号

    SIGSTOP--程序键盘中止信号

    SIGSEGV--程序无效内存中止信号

    SIGBUS--程序内存字节未对齐中止信号

    SIGPIPE--程序Socket发送失败中止信号

    单独创建一个异常捕获的类 CaughtExceptionHandler。这个类在 appFinsh 方法中初始化。

    + (void)initHandler

    {

         NSSetUncaughtExceptionHandler(&HandleException);

         signal(SIGABRT, SignalHandler);

          signal(SIGILL, SignalHandler);

          signal(SIGSEGV, SignalHandler);

          signal(SIGFPE, SignalHandler);

           signal(SIGBUS, SignalHandler);

           signal(SIGPIPE, SignalHandler);

    }

    HandleException 函数是用来处理系统抛出的 Expcetion 异常。

    void HandleException(NSException *exception)

    {

            [[[CaughtExceptionHandler alloc] init]  performSelectorOnMainThread:@selector(handleException:) withObject:exception waitUntilDone:YES]; // 主线程执行 handleException 方法

    }

    SignalHandler 捕获系统发出的信号

    void SignalHandler(int signal)

    {

         int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount); // 32位并发的原子操作数

         if (exceptionCount > UncaughtExceptionMaximum) {

              return;

         }

        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];

        NSArray *callStack = [NSThread callStackSymbols]; // 获取调用函数栈

      [userInfo setObject:callStack forKey:CaughtExceptionHandlerAddressesKey];

        NSException *exception = [NSException exceptionWithName:CaughtExceptionHandlerSignalExceptionName reason:[NSString stringWithFormat:NSLocalizedString(@"Signal %@ was raised.", nil), @(signal)] userInfo:userInfo]; // 将 Signal 信号转成 NSException 异常传出

      [[[CaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:) withObject:exception waitUntilDone:YES];

    }

    handleException 函数将 Exception 对象转为字典,通过通知将其带出。性能处理类接收该类通知通过通知对象获取字典,将字典上传服务器。

    - (void)handleException:(NSException *)exception

    {

          NSTimeInterval crashTime = [[NSDate date] timeIntervalSince1970] * 1000; //毫秒级

          NSString *name = [exception name]; //异常名称

          NSString *reason = [exception reason]; //异常原因

          NSString *callStackSymbols = [[exception callStackSymbols] componentsJoinedByString:@"\n"];

          if (callStackSymbols && callStackSymbols.length > 0) {

                 NSArray *callStack = [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey];

                 if (callStack.count > 0) {

                      callStackSymbols = [callStack componentsJoinedByString:@"\n"];

                 }

          }

          NSInteger crashType = 1; //异常类型

          NSInteger netType = 0; //网络类型

          NSInteger screenType = 1; //横竖屏

           NSString *memoryInfo = [self currentMemoryInfo]; //剩余内存

           NSString *pageName = @""; //当前页面路径

           NSMutableDictionary *crashDic = [NSMutableDictionary dictionary];

           [crashDic setObject:@(crashTime) forKey:ExceptionTime];

           [crashDic setObject:XT_NSSTRING_NOT_NIL(pageName) forKey:ExceptionPageName];

           [crashDic setObject:XT_NSSTRING_NOT_NIL(name) forKey:ExceptionName];

           [crashDic setObject:XT_NSSTRING_NOT_NIL(reason) forKey:ExceptionReason];

           [crashDic setObject:XT_NSSTRING_NOT_NIL(callStackSymbols) forKey:ExceptionStack];

            [crashDic setObject:@(crashType) forKey:ExceptionCrashType];

            [crashDic setObject:@(netType) forKey:ExceptionNetType];

            [crashDic setObject:@(screenType) forKey:ExceptionScreenType];

             [crashDic setObject:XT_NSSTRING_NOT_NIL(memoryInfo) forKey:ExceptionMemoryInfo];

             NSLog(@"crashCatcher has catch the crash %@, crash Reason is %@, crash Stack is %@", name, reason, callStackSymbols);

    //发送通知

              NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];

    [notificationCenter postNotificationName:BFCrashCatcherCatchNotification object:nil userInfo:crashDic];

           CFRunLoopRef runLoop = CFRunLoopGetCurrent();

           CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);

           while (!self.dismissed) {

                  for (NSString *mode in (__bridge NSArray *)allModes) {

                        CFRunLoopRunInMode((__bridge CFStringRef)mode, 0.001, false);

                   }

            }

            CFRelease(allModes);

             NSSetUncaughtExceptionHandler(NULL);

             signal(SIGABRT, SIG_DFL);

              signal(SIGILL, SIG_DFL);

              signal(SIGSEGV, SIG_DFL);

               signal(SIGFPE, SIG_DFL);

               signal(SIGBUS, SIG_DFL);

               signal(SIGPIPE, SIG_DFL);

              if ([[exception name] isEqual:UncaughtExceptionHandlerSignalExceptionName]) {

                      kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);

               } else {

                      [exception raise];

                }

    }

    相关文章

      网友评论

          本文标题:异常捕获上传服务器

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