这个问题是针对Linux的,使用GCC编译器。
如果在一个本来用于捕获SIGSEGV的信号处理程序中发生了SIGSEGV(我指的是通常会导致SIGSEGV的违规行为),会发生什么行为?以下是一个代码示例,以帮助讨论:
/* In main or whatever */
{
struct sigaction sa = {}; /* initialised to all zero (I vote for GCC style breach of standard here) */
sa.sa_handler = DisasterSignals;
sa.sa_flags = SA_RESETHAND | SA_NODEFER; /* To have or have not */
sigaction(SIGSEGV, &sa, NULL);
}
static void DisasterSignals(int signal)
{
/* We cannot save the situation, the purpose of catching the signal is
only to do something clever to aid debugging before we go. */
/* Q: What if we segfault in here?? */
abort(); /* This should give us the expected core dump (if we survive to this point) */
}
想象一下,在点“Q”处有一个有问题的机器指令。
1)没有使用SA_RESETHAND | SA_NODEFER
:这似乎将系统置于逻辑陷阱中:在“Q”处,应该生成SIGSEGV信号。但是,信号处理程序中阻止了SIGSEGV信号(默认的sigaction行为)。执行如何继续?会冻结吗?它会跳过有问题的指令吗(我猜测不会)?
2)使用SA_RESETHAND | SA_NODEFER
:我猜在这种情况下,当SIGSEGV信号重复时,程序将以“正常”的方式崩溃。
3)只使用SA_NODEFER
:我猜在这种情况下,当SIGSEGV信号重复时,信号处理程序将被递归调用;如果SIGSEGV信号总是重复,则会冻结直到堆栈溢出,然后会发生什么。