|
|
//
|
|
|
// YHCrashReporter.m
|
|
|
// YH_Analytics
|
|
|
//
|
|
|
// Created by 王钱钧 on 15/2/4.
|
|
|
// Copyright (c) 2015年 YOHO. All rights reserved.
|
|
|
//
|
|
|
|
|
|
#import "YHCrashReporter.h"
|
|
|
#import "YH_Analytics.h"
|
|
|
#import "YHError.h"
|
|
|
#include <signal.h>
|
|
|
#include <execinfo.h>
|
|
|
|
|
|
#pragma mark - C Fuctions
|
|
|
|
|
|
void sighandler(int signal)
|
|
|
{
|
|
|
const char* names[NSIG];
|
|
|
names[SIGABRT] = "SIGABRT";
|
|
|
names[SIGBUS] = "SIGBUS";
|
|
|
names[SIGFPE] = "SIGFPE";
|
|
|
names[SIGILL] = "SIGILL";
|
|
|
names[SIGPIPE] = "SIGPIPE";
|
|
|
names[SIGSEGV] = "SIGSEGV";
|
|
|
|
|
|
YHCrashReporter *crash = [YHCrashReporter sharedInstance];
|
|
|
|
|
|
NSArray *arr = [crash callstackAsArray];
|
|
|
NSDictionary *userInfo = @{
|
|
|
JsonKeyCrashCallstack : arr,
|
|
|
JsonKeyCrashSignal : @(signal),
|
|
|
JsonKeyCrashSignalName : [NSString stringWithUTF8String:names[signal]],
|
|
|
};
|
|
|
[crash performSelectorOnMainThread:@selector(handleSignal:) withObject:userInfo waitUntilDone:YES];
|
|
|
}
|
|
|
|
|
|
void uncaughtCrashExceptionHandler(NSException *exception)
|
|
|
{
|
|
|
YHCrashReporter *crash = [YHCrashReporter sharedInstance];
|
|
|
|
|
|
NSArray *arr = [exception callStackSymbols];
|
|
|
NSDictionary *userInfo = @{
|
|
|
JsonKeyCrashCallstack : arr,
|
|
|
JsonKeyCrashExceptionName : exception.name,
|
|
|
JsonKeyCrashExceptionReason : exception.reason,
|
|
|
};
|
|
|
[crash performSelectorOnMainThread:@selector(handleNSException:) withObject:userInfo waitUntilDone:YES];
|
|
|
}
|
|
|
|
|
|
|
|
|
@implementation YHCrashReporter
|
|
|
|
|
|
|
|
|
+ (YHCrashReporter *)sharedInstance
|
|
|
{
|
|
|
static YHCrashReporter *sharedInstance = nil;
|
|
|
|
|
|
static dispatch_once_t onceToken;
|
|
|
dispatch_once(&onceToken, ^{
|
|
|
sharedInstance = [[YHCrashReporter alloc] init];
|
|
|
});
|
|
|
|
|
|
return sharedInstance;
|
|
|
}
|
|
|
|
|
|
#pragma mark - Lifetime methods
|
|
|
|
|
|
- (id)init
|
|
|
{
|
|
|
self = [super init];
|
|
|
if (self) {
|
|
|
signal(SIGABRT, sighandler);
|
|
|
signal(SIGBUS, sighandler);
|
|
|
signal(SIGFPE, sighandler);
|
|
|
signal(SIGILL, sighandler);
|
|
|
signal(SIGPIPE, sighandler);
|
|
|
signal(SIGSEGV, sighandler);
|
|
|
|
|
|
NSSetUncaughtExceptionHandler(&uncaughtCrashExceptionHandler);
|
|
|
}
|
|
|
|
|
|
return self;
|
|
|
}
|
|
|
|
|
|
- (void)dealloc
|
|
|
{
|
|
|
signal(SIGABRT, SIG_DFL);
|
|
|
signal(SIGBUS, SIG_DFL);
|
|
|
signal(SIGFPE, SIG_DFL);
|
|
|
signal(SIGILL, SIG_DFL);
|
|
|
signal(SIGPIPE, SIG_DFL);
|
|
|
signal(SIGSEGV, SIG_DFL);
|
|
|
|
|
|
NSSetUncaughtExceptionHandler(NULL);
|
|
|
}
|
|
|
|
|
|
#pragma mark - methods
|
|
|
|
|
|
- (NSArray *)callstackAsArray
|
|
|
{
|
|
|
void *callstack[128];
|
|
|
const int numFrams = backtrace(callstack, 128);
|
|
|
char **symbols = backtrace_symbols(callstack, numFrams);
|
|
|
|
|
|
NSMutableArray *arr = [NSMutableArray arrayWithCapacity:numFrams];
|
|
|
for (int i = 0; i < numFrams; i++) {
|
|
|
[arr addObject:[NSString stringWithUTF8String:symbols[i]]];
|
|
|
}
|
|
|
|
|
|
free(symbols);
|
|
|
|
|
|
return arr;
|
|
|
}
|
|
|
|
|
|
- (void)handleSignal:(NSDictionary*)userInfo
|
|
|
{
|
|
|
YALog(@"crash============:\n%@", userInfo);
|
|
|
if (!userInfo || ![userInfo isKindOfClass:[NSDictionary class]]) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
[[YH_Analytics sharedInstance] logError:kErrorTypeCrash parameters:@{ JsonKeyErrorST: userInfo}];
|
|
|
}
|
|
|
|
|
|
- (void)handleNSException:(NSDictionary*)userInfo
|
|
|
{
|
|
|
YALog(@"crash============:\n%@", userInfo);
|
|
|
if (!userInfo || ![userInfo isKindOfClass:[NSDictionary class]]) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
[[YH_Analytics sharedInstance] logError:kErrorTypeCrash parameters:@{ JsonKeyErrorST: userInfo}];
|
|
|
}
|
|
|
|
|
|
@end |