解决方法
这是一个使用sigaltstack捕获无限递归的最小示例程序.如果您注释掉sigaltstack调用或SA_ONSTACK标志,信号处理程序将无法运行,因为它没有堆栈,程序将崩溃.
#define _XOPEN_SOURCE 700 #include <signal.h> #include <unistd.h> void handler(int sig) { write(2,"stack overflow\n",15); _exit(1); } unsigned infinite_recursion(unsigned x) { return infinite_recursion(x)+1; } int main() { static char stack[SIGSTKSZ]; stack_t ss = { .ss_size = SIGSTKSZ,.ss_sp = stack,}; struct sigaction sa = { .sa_handler = handler,.sa_flags = SA_ONSTACK }; sigaltstack(&ss,0); sigfillset(&sa.sa_mask); sigaction(SIGSEGV,&sa,0); infinite_recursion(0); }
更复杂的使用实际上可能会执行siglongjmp跳出信号处理程序并返回到可以避免无限递归的一个点.如果正在使用异步信号不安全的库调用,或者您的数据可能处于不安全/不可恢复的状态,但如果执行纯算术运算,则该操作可能是有效的.
也许信号处理程序的一个更好的任务是执行任何尚未保存到磁盘的有用/关键数据的紧急转储.如果您不能调用异步信号不安全的功能,这可能很困难,但如果您付出了一些努力,通常可能会发生这种情况.