【发布时间】:2016-01-20 20:04:08
【问题描述】:
这个问题是针对 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 总是重复,我们会冻结,直到堆栈溢出,然后是什么。
【问题讨论】:
-
Quis custodiet ipsos custodes?
-
您应该只在信号处理程序中调用可重入函数。
-
coliru.stacked-crooked.com/a/40fc467ac87e9cfa 我的结果显示:1&2 - 处理程序中的段错误立即使程序崩溃。 3 - 信号处理程序递归大约 13k 次(变化)然后崩溃。
-
man7.org/linux/man-pages/man2/sigprocmask.2.html - 逻辑陷阱的答案:" 如果 SIGBUS、SIGFPE、SIGILL 或 SIGSEGV 在被阻塞时生成,则结果未定义,除非信号是由 kill(2) 生成的、sigqueue(3) 或 raise(3)。"
-
您不能将 cmets 标记为已接受的答案,但您可以标记答案。