在上一篇章中,介绍了 KSCrash 的注册流程。其中在 kscm_setActiveMonitors 方法里遍历 g_monitors 数组,对各种类型的崩溃进行一一注册操作。这一篇章就来挨个分析下各种类型的崩溃是如果添加监控,以及如果处理崩溃的。
我们就主要分析以下几种典型崩溃类型的处理:
- Mach kernel exceptions
- Fatal signals
- C++ exceptions
- Objective-C exceptions
- Main thread deadlock (experimental)
几乎都是相同的处理思路:
第一步调用 getAPI 方法,
第二步调用 setEnabled 方法,
第三步调用 install 方法添加监控,
第四步调用 handle 方法处理捕获到的崩溃事件。
接下来,我们一一查看具体的代码内容。
Mach kernel exceptions
1、getAPI
进入 kscm_machexception_getAPI 方法,该方法的具体内容:
1 | KSCrashMonitorAPI* kscm_machexception_getAPI() |
2、setEnabled
在 setEnabled 方法里会对当前崩溃类型添加监控,该方法的具体内容:
1 | static void setEnabled(bool isEnabled) |
3、install
在上述方法里会根据 isEnabled 值来进行 install or uninstall。主要来看下 installExceptionHandler 方法:
1 | static bool installExceptionHandler() |
4、handle
然后来看异常处理函数 handleExceptions:
1 | static void* handleExceptions(void* const userData) |
其中进入 kscm_handleException 函数,该方法的具体内容:
1 | void kscm_handleException(struct KSCrash_MonitorContext* context) |
我们看到调用了 g_onExceptionEvent 函数,该函数会调用 onCrash 方法。onCrash 方法的具体内容,我们会在后续篇章分析。现在,我们进入下一崩溃类型的监控分析。
Fatal signals
1、getAPI
进入 kscm_signal_getAPI 方法,该方法的具体内容:
1 | KSCrashMonitorAPI* kscm_signal_getAPI() |
2、setEnabled
在 setEnabled 方法里会对当前崩溃类型添加监控,该方法的具体内容:
1 | static void setEnabled(bool isEnabled) |
3、install
在这个方法里会根据 isEnabled 值来进行 install or uninstall。主要来看下 installSignalHandler 方法:
1 | static bool installSignalHandler() |
其中遍历的数据,即所支持的所有 sinal 类型为:
1 | static const int g_fatalSignals[] = |
4、handle
然后来看异常处理函数 handleSignal:
1 | static void handleSignal(int sigNum, siginfo_t* signalInfo, void* userContext) |
其中,能看到同样调用了 kscm_handleException 函数。
C++ exceptions
1、getAPI
进入 kscm_cppexception_getAPI 方法,该方法的具体内容:
1 | extern "C" KSCrashMonitorAPI* kscm_cppexception_getAPI() |
2、setEnabled
在 setEnabled 方法里会对当前崩溃类型添加监控,该方法的具体内容:
1 | static void setEnabled(bool isEnabled) |
3、CPPExceptionTerminate
在这个方法里会根据 isEnabled 值来决定是否添加监控,即执行 CPPExceptionTerminate 方法:
1 | static void CPPExceptionTerminate(void) |
其中,能看到同样调用了 kscm_handleException 函数。
Objective-C exceptions
1、getAPI
进入 kscm_nsexception_getAPI 方法,该方法的具体内容:
1 | KSCrashMonitorAPI* kscm_nsexception_getAPI() |
2、setEnabled
在 setEnabled 方法里会对当前崩溃类型添加监控,该方法的具体内容:
1 | static void setEnabled(bool isEnabled) |
3、handle
在这个方法里会根据 isEnabled 值来执行 NSSetUncaughtExceptionHandler,设置机场处理函数 handleUncaughtException:
1 | static void handleUncaughtException(NSException* exception) { |
其中,能看到同样调用了 kscm_handleException 函数。
Main thread deadlock (experimental)
1、getAPI
进入 kscm_deadlock_getAPI 方法,该方法的具体内容:
1 | KSCrashMonitorAPI* kscm_deadlock_getAPI() |
2、setEnabled
在 setEnabled 方法里会对当前崩溃类型添加监控,该方法的具体内容:
1 | static void setEnabled(bool isEnabled) |
3、KSCrashDeadlockMonitor
具体的处理都在 KSCrashDeadlockMonitor 这个类里。
逻辑就是:开启一个定时线程,将全局的 bool 字段 awaitingResponse 设为 YES,然后切换到主线程将 awaitingResponse 再设置为 NO。若监测到 awaitingResponse 字段没有变为 NO,说明主线程死锁。
1 | - (id) init |
4、handle
其中,处理异常的函数为 handleDeadlock:
1 | - (void) handleDeadlock |
其中,能看到同样调用了 kscm_handleException 函数。
小结
KSCrash 主要支持的崩溃类型就是以上这些。g_monitors 数组里的其他崩溃类型大家可以自行了解。后续篇章中我们进入 kscm_handleException 流程,分析捕获到崩溃之后收集堆栈信息的操作。