Ben collapse iOS done manually collect information

Ben collapse iOS done manually collect information

In the daily development work, App will be different in different application scenarios of users, in order to improve the reliability and stability of the App, we may need to collect some crash report that appears when users use the App, the following function is to collect user crash of concrete measures appear in daily use, you only need to correspond to the NSExceptionparsed assembled into what you need to upload to the server, you can locate the problem by crash data in conjunction with a local file server.

First, the system crash

Program for the system crash caused by abnormal exit, we can UncaughtExceptionHandlercapture mechanism, instead of using a custom functionExceptionHandler

Second, signal processing

The amount of the signal system can not catch the exception, we need to use the standard unix signal mechanism, the registered handler when SIGABRT, SIGBUS, SIGSEGV signal generation and so on.

Third, coding practices

void installUncaughtExceptionHandler(void) {
    //设置系统异常捕获函数
    NSSetUncaughtExceptionHandler(&exceptionHandler);
    //设置Signal信息处理
    signal(SIGABRT, signalHandler);
    signal(SIGILL, signalHandler);
    signal(SIGSEGV, signalHandler);
    signal(SIGFPE, signalHandler);
    signal(SIGBUS, signalHandler);
    signal(SIGPIPE, SIG_IGN);
}

In the above code, we will the system be able to capture as what bounds of the array class exception thrown to the custom methods exceptionHandler, in the method, we can obtain all the information system exceptions, and then caught exception information is assembled into NSExceptionpassed

// 可捕获异常在此进行处理
void exceptionHandler(NSException *exception) {
    if (!exception) {
        return;
    }

    int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
    if (exceptionCount > UncaughtExceptionMaximum) {
        DEBUGLOG(@"Exception异常数超过最大异常处理数");
        exitApplication();
        return;
    }

    NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
    [userInfo setObject:[exception callStackSymbols] forKey:ExceptionCallStacks];

    NSException *exc = [NSException exceptionWithName:[exception name]
                                               reason:[exception reason]
                                             userInfo:userInfo];

    [[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:)
                                                              withObject: exc
                                                           waitUntilDone:YES];
}

// 异常的信号量操作在此处理
void signalHandler(int signal) {
    int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
    if (exceptionCount > UncaughtExceptionMaximum) {
        DEBUGLOG(@"Signal异常数超过最大异常处理数, signal = %d.", signal);
        exitApplication();
        return;
    }

    NSString *reason = [NSString stringWithFormat:@"Signal %d was raised.", signal];

    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    [userInfo setObject:[NSNumber numberWithInt:signal] forKey:SignalExceptionKey];
	[userInfo setObject:[[UncaughtExceptionHandler backtrace] copy] forKey:ExceptionCallStacks];
	// 组装成NSException 对象
    NSException *exc = [NSException exceptionWithName:SignalExceptionName
                                               reason:reason
                                             userInfo:userInfo];

    [[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:)
                                                              withObject:exc
                                                           waitUntilDone:YES];
}

+ (NSArray *)backtrace {
    //设置保存调用堆栈的buffer最大为64,调用backtrace用来获取当前线程的调用堆栈,获取的信息存放在这里的callstack
    void *callstack[64];
    int frames = backtrace(callstack, 64);
    char **strs = backtrace_symbols(callstack, frames);

    NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
    for (int i = 0; i < frames; i++) {
        [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
    }
    free(strs);

    return backtrace;
}

// 异常处理操作,在这里可以将NSException 解析成你所需要上传到云端的分析文件,以便进行用户crash 数据的收集
- (void)handleException:(NSException *)exception {
	
    NSString *name = [exception name];
    NSString *reason = [exception reason];
    NSArray *callStack = [[exception userInfo] objectForKey:ExceptionCallStacks];

    //组合崩溃信息并进行输出及保存
    NSString *exceptionInfo = @"\n=============== Exception Info ===============\n";
    exceptionInfo = [exceptionInfo stringByAppendingFormat:@"Exception Name: %@\n", name];
    exceptionInfo = [exceptionInfo stringByAppendingFormat:@"Exception Reason: %@\n", reason];
    exceptionInfo = [exceptionInfo stringByAppendingFormat:@"Exception Call Stack: %@\n", callStack];
}
Published 17 original articles · won praise 2 · views 10000 +

Guess you like

Origin blog.csdn.net/Abe_liu/article/details/103944991