发布的app难免会出现一些奇葩的bug,为了能够实时跟踪app的崩溃,需要接管系统的异常捕获接口,自己来收集保存崩溃现场信息。
下面简单说一下几个平台的异常崩溃捕获。
1.iOS
1.1 Exception
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | -(BOOL)install{ if(NSGetUncaughtExceptionHandler() != custom_exceptionHandler) oldhandler = NSGetUncaughtExceptionHandler(); if(self->_handlerEnable){ NSSetUncaughtExceptionHandler(&custom_exceptionHandler); }else{ DDLogWarning(@"NSEXception handler disable"); } return YES; } -(BOOL)uninstall{ NSSetUncaughtExceptionHandler(oldhandler); return YES; } |
1.2 Signal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | -(BOOL)install{ if(installed){ DDLogError(@"signal handler has been installed"); return NO; } custom_crash_stk.ss_size = MAX(MINSIGSTKSZ, 64*1024); custom_crash_stk.ss_sp = malloc(custom_crash_stk.ss_size); custom_crash_stk.ss_flags = 0; if(custom_crash_stk.ss_sp == NULL){ return NO; } //替换信号处理函数栈,避免栈已经耗尽,导致进程退出 if(sigaltstack(&custom_crash_stk, 0) < 0) return NO; if(!sa_preHandlers){ sa_preHandlers = (struct sigaction*)malloc(sizeof(struct sigaction) * monitored_signals_count); memset(sa_preHandlers, 0, sizeof(struct sigaction) * monitored_signals_count); } struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_SIGINFO | SA_ONSTACK; sigemptyset(&sa.sa_mask); sa.sa_sigaction = &custom_signalHandler; for (int i = 0; i < monitored_signals_count; i++) { if(sigaction(monitored_signals[i], &sa, (struct sigaction*)(sa_preHandlers+i)) != 0){ DDLogError(@"install signalHandler failed, uninstall it!"); [self uninstall]; return NO; } } installed = 1; return YES; } -(BOOL)uninstall{ if(installed){ if(custom_crash_stk.ss_sp){ free(custom_crash_stk.ss_sp); custom_crash_stk.ss_sp = nil; } for (int i = 0; i < monitored_signals_count; i++) { if(sigaction(monitored_signals[i], (struct sigaction*)(sa_preHandlers+i), 0) != 0){ return NO; } } if(sa_preHandlers) free(sa_preHandlers); installed = 0; return YES; }else{ DDLogError(@"signalHandler already uninstalled!"); return NO; } } |
2.Cocos
2.1 Cocos-Lua
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | local function handleLuaException(msg) if msg==nil then return end local targetPlatform = cc.Application:getInstance():getTargetPlatform() local supportObjectCBridge = false if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) or (cc.PLATFORM_OS_MAC == targetPlatform) then supportObjectCBridge = true end local supportJavaBridge = false if (cc.PLATFORM_OS_ANDROID == targetPlatform) then supportJavaBridge = true end if (supportJavaBridge == true) then //... elseif (supportObjectCBridge == true) then //... end end function __G__TRACKBACK__(msg) handleLuaException(msg) return msg end |
2.2 Cocos-JS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //注册异常处理回调函数 void JSExceptionHandler::registerJSExceptionHandler(JSContext *cx) { JS_SetErrorReporter(cx, JSExceptionHandler::reportError); } void JSExceptionHandler::reportError(JSContext *cx, const char *message, JSErrorReport *report) { const char* format = "%s:%u:%s\n"; const char* fileName = report->filename ? report->filename : "no filename"; int bufLen = strlen(format) + strlen(fileName) + strlen(message) + 16; char* traceback = (char*)malloc(bufLen); memset(traceback, 0, bufLen); sprintf(traceback, format, fileName, (unsigned int) report->lineno, message); //.... free(traceback); }; |
3.U3D
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //注册未处理异常回调 System.AppDomain.CurrentDomain.UnhandledException += _OnUnhandledExceptionHandler; //注册日志回调 Application.RegisterLogCallback(_OnLogCallbackHandler); static private void _OnLogCallbackHandler(string name, string stack, LogType type) { //… } private static void _OnUnhandledExceptionHandler(object sender, System.UnhandledExceptionEventArgs args) { if (args.ExceptionObject.GetType() == typeof(System.Exception)) { //… } } |
Permalink
每个平台都会出现BUG
Permalink
能实现实时跟踪,也能减少很多bug引起的后续问题
Permalink
博客是主题非常好看