第二个参数 sigaction 结构体指针,用于声明当某个特定信号发生的时候,应该如何处理。
第三个参数也是 sigaction 结构体指针,他表示的是默认处理方式,当我们自定义了信号量处理的时候,用他存储之前默认的处理方式。
这也是指针与引用的区别,指针操作操作的都是变量本身,所以给新指针赋值了以后,需要另一个指针来记录封装了默认处理方式的变量在内存中的位置。
所以,要订阅异常发生的信号,最简单的做法就是直接用一个循环遍历所有要订阅的信号,对每个信号调用sigaction()
void init() {
struct sigaction handler;
struct sigaction old_signal_handlers[SIGNALS_LEN];
for (int i = 0; i < SIGNALS_LEN; ++i) {
sigaction(signal_array[i], &handler, & old_signal_handlers[i]);
}
}
捕获到 Crash 的位置
sigaction 结构体有一个 sa_sigaction
变量,他是个函数指针,原型为:void (*)(int siginfo_t *, void *)
因此,我们可以声明一个函数,直接将函数的地址赋值给sa_sigaction
void signal_handle(int code, siginfo_t *si, void *context) {
}
void init() {
struct sigaction old_signal_handlers[SIGNALS_LEN];
struct sigaction handler;
handler.sa_sigaction = signal_handle;
handler.sa_flags = SA_SIGINFO;
for (int i = 0; i < SIGNALS_LEN; ++i) {
sigaction(signal_array[i], &handler, & old_signal_handlers[i]);
}
}
这样当发生 Crash 的时候就会回调我们传入的signal_handle()
函数了。在signal_handle()
函数中,我们得要想办法拿到当前执行的代码信息。
设置紧急栈空间
如果当前函数发生了无限递归造成堆栈溢出&