// // ExceptionHandler.m // IBOSS // // Created by ssl on 2018/3/2. // Copyright © 2018年 elongtian. All rights reserved. // #import "ExceptionHandler.h" #include #include NSString * const ExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName"; NSString * const ExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey"; NSString * const ExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey"; volatile int32_t UncaughtExceptionCount = 0; const int32_t UncaughtExceptionMaximum = 10; const NSInteger ExceptionHandlerSkipAddressCount = 4; const NSInteger ExceptionHandlerReportAddressCount = 5; @implementation ExceptionHandler + (NSArray *)backtrace { void * callstack[128]; int frames = backtrace(callstack, 128); char **strs = backtrace_symbols(callstack, frames); int i; NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames]; for ( i = ExceptionHandlerSkipAddressCount; i < ExceptionHandlerSkipAddressCount + ExceptionHandlerReportAddressCount; i++) { [backtrace addObject:[NSString stringWithUTF8String:strs[i]]]; } free(strs); return backtrace; } - (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex { if (anIndex == 0) { dismissed = YES; } } - (void)validateAndSaveCriticalApplicationData { } - (void)handleException:(NSException *)exception { [self validateAndSaveCriticalApplicationData]; // 找到Documents文件夹路径 NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *dataFilePath = [documentsPath stringByAppendingPathComponent:IBOSSERROR]; NSFileManager *fileManager = [NSFileManager defaultManager]; BOOL isDir = NO; // fileExistsAtPath 判断一个文件或目录是否有效,isDirectory判断是否一个目录 BOOL existed = [fileManager fileExistsAtPath:dataFilePath isDirectory:&isDir]; if ( !(isDir == YES && existed == YES) ) { // 在 Document 目录下创建一个 head 目录 [fileManager createDirectoryAtPath:dataFilePath withIntermediateDirectories:YES attributes:nil error:nil]; } NSString *str = [exception reason]; //需要知道字符串最终存储的地方,所以需要创建一个路径去存储字符串 NSString *strPath = [dataFilePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.log",[self getCurrentTimes]]]; [str writeToFile:strPath atomically:YES encoding:NSUTF8StringEncoding error:nil]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; CFRunLoopRef runLoop = CFRunLoopGetCurrent(); CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop); while (!dismissed) { for (NSString *mode in (__bridge NSArray *)allModes) { CFRunLoopRunInMode((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:ExceptionHandlerSignalExceptionName]) { kill(getpid(), [[[exception userInfo] objectForKey:ExceptionHandlerSignalKey] intValue]); } else { [exception raise]; } } -(NSString*)getCurrentTimes{ NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; // ----------设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制 [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; //现在时间,你可以输出来看下是什么格式 NSDate *datenow = [NSDate date]; //----------将nsdate按formatter格式转成nsstring NSString *currentTimeString = [formatter stringFromDate:datenow]; return currentTimeString; } @end void HandleException(NSException *exception) { int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount); if (exceptionCount > UncaughtExceptionMaximum) { return; } NSArray *callStack = [ExceptionHandler backtrace]; NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]]; [userInfo setObject:callStack forKey:ExceptionHandlerAddressesKey]; [[[ExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:) withObject: [NSException exceptionWithName:[exception name] reason:[exception reason] userInfo:userInfo] waitUntilDone:YES]; } void SignalHandler(int signal) { int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount); if (exceptionCount > UncaughtExceptionMaximum) { return; } NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:ExceptionHandlerSignalKey]; NSArray *callStack = [ExceptionHandler backtrace]; [userInfo setObject:callStack forKey:ExceptionHandlerAddressesKey]; [[[ExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:) withObject: [NSException exceptionWithName:ExceptionHandlerSignalExceptionName reason: [NSString stringWithFormat: NSLocalizedString(@"Signal %d was raised.", nil), signal] userInfo: [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:ExceptionHandlerSignalKey]] waitUntilDone:YES]; } void InstallUncaughtExceptionHandler(void){ NSSetUncaughtExceptionHandler(&HandleException); signal(SIGABRT, SignalHandler); signal(SIGILL, SignalHandler); signal(SIGSEGV, SignalHandler); signal(SIGFPE, SignalHandler); signal(SIGBUS, SignalHandler); signal(SIGPIPE, SignalHandler); }