一、介绍
在工程TestDtPorterv中调用的getRunner().start(bAsync) 有使用到程序的异常捕获处理
void install_signal_hooks(TracerLogCallback cbLog, ExitHandler sigHandler = NULL)
{
g_cbSignalLog = cbLog;
g_exitHandler = sigHandler;
for (int s = 1; s < NSIG; s++)
{
signal(s, handle_signal);
}
}
install_signal_hooks([this](const char* message) {
if(!_to_exit)
WTSLogger::error(message);
}, [this](bool toExit) {
if (_to_exit)
return;
_to_exit = toExit;
WTSLogger::info("Exit flag is {}", _to_exit);
});
二、信号安装机制
void install_signal_hooks(TracerLogCallback cbLog, ExitHandler sigHandler) {
g_cbSignalLog = cbLog; // 设置日志回调
g_exitHandler = sigHandler; // 设置退出回调
// ⭐关键:为所有信号安装统一处理函数⭐
for (int s = 1; s < NSIG; s++) {
signal(s, handle_signal);
}
}
三、信号处理系统
而信号的捕获处理主要在文件SignalHook.h中,该文件主要为跨平台的信号处理系统,用于捕获和处理程序运行时的各种系统信号
1. Windows平台信号处理
用户中断信号
case SIGINT: // Ctrl+C 中断
case SIGBREAK: // Ctrl+Break 序列
g_cbSignalLog("app interrupted");
if (g_exitHandler)
g_exitHandler(signum); // 优雅退出
else
exit(signum); // 直接退出
break;
严重错误信号(需要调用栈)
case SIGILL: // 非法指令
case SIGFPE: // 浮点异常
case SIGSEGV: // 段错误
case SIGABRT: // 异常终止
sprintf(buf, "app stopped by signal %d", signum);
g_cbSignalLog(buf);
print_stack_trace(g_cbSignalLog); // ⭐打印调用栈⭐
// 然后退出...
2. Linux/Unix平台信号处理
可忽略的信号
case SIGURG: // socket紧急条件
case SIGCONT: // 继续执行
case SIGCHLD: // 子进程状态改变
case SIGIO: // I/O可用
case SIGWINCH: // 窗口大小改变
sprintf(buf, "app discard signal %d", signum);
g_cbSignalLog(buf);
break; // ⭐只记录,不退出⭐
进程控制信号
case SIGSTOP: // 停止进程(无法捕获)
case SIGTSTP: // 键盘停止信号(Ctrl+Z)
case SIGTTIN: // 后台读终端
case SIGTTOU: // 后台写终端
sprintf(buf, "app stopped by signal %d", signum);
g_cbSignalLog(buf);
// 执行退出处理...
严重错误信号(生成core dump)
case SIGQUIT: // 退出程序
case SIGILL: // 非法指令
case SIGTRAP: // 跟踪陷阱
case SIGABRT: // 异常终止
case SIGFPE: // 浮点异常
case SIGBUS: // 总线错误
case SIGSEGV: // 段错误
g_cbSignalLog("segmentation violation");
print_stack_trace(g_cbSignalLog); // ⭐打印调用栈⭐
// 退出处理...
四、堆栈打印系统
堆栈处理主要在文件StackWalker.h中,StackWalker是一个用于遍历程序调用栈的工具类,它能够:
- 获取当前线程的函数调用链
- 解析函数名、文件名、行号等调试信息
- 将调用栈信息格式化输出
比如在程序崩溃时会打印具体的崩溃信息
install_signal_hooks([](const char* message) {
std::cout << message << std::endl;
}, [](bool toExit) {
std::cout << "Exit flag is {}" << toExit << std::endl;
});
while (1) {
Sleep(2000);
char* p = nullptr;
std::cout << *p << std::endl;
}