发布的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 ) ) { //… } } |