C语言 SIGSEGV 不能通过 sigaction 被捕获两次



下面的代码在第二个printf有分割错误,而这应该被处理(setjmp(。请注意,由于格式字符串错误,每个printf都会创建分段错误。第一个分段错误得到正确处理,但第二个分段错误没有得到正确处理(在注释掉任一printf后运行代码都不会出现段错误(。

#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
static jmp_buf escapeCallJmpBuf;
static void sigsegv_handler(int signal, siginfo_t *info, void *context) {
longjmp(escapeCallJmpBuf, 1);
}
int main(int argc, char **argv) {
struct sigaction segvAction, segvActionOld;
segvAction.sa_handler = 0;
memset(&segvAction.sa_mask, 0, sizeof(segvAction.sa_mask));
segvAction.sa_flags = SA_SIGINFO;
segvAction.sa_sigaction = sigsegv_handler;
sigaction(SIGSEGV, &segvAction, &segvActionOld);
int res;
// Catch first segmentation fault
if (setjmp(escapeCallJmpBuf)) {
res = 1;
} else {
printf ("%sn", 2); // This will segfault
res = 0;
}
// try to catch second segmentation fault
if (setjmp(escapeCallJmpBuf)) {
res = 2;
} else {
printf ("%sn", 3); // This will segfault
res = 0;
}
sigaction(SIGSEGV, &segvActionOld, 0);
return res;
}

setjmplongjmp不一定会恢复信号掩码(取决于实现(。可能发生的情况是在处理第一个SIGSEGV后,信号掩码恢复为默认值。因此,第二个SIGSEGV不会被捕获,即默认操作而不是您的操作发生,即退出进程。

您应该改用sigsetjmpsiglongjmp

POSIX指出:

没有指定 longjmp(( 是恢复信号掩码、保持信号掩码不变还是将其恢复到调用 setjmp(( 时的值。

并建议:

其行为取决于信号模板值的应用 不应该使用 longjmp(( 和 setjmp((,因为它们对 信号掩码未指定,但应使用 siglongJMP(( 和 sigsetjmp(( 函数(可以保存和恢复信号掩码( 在应用程序控制下(。

此外,从信号处理程序跳转也有限制:

建议应用程序不要调用 longjmp(( 或 来自信号处理程序的 siglongjmp((。避免在以下情况下出现未定义的行为 从信号处理程序调用这些函数,应用程序需要 确保以下两件事之一:

在调用 longjmp(( 或 siglongjmp(( 之后,进程只调用 异步信号安全函数,并且不会从初始调用返回 到 main((。

任何其处理程序调用 longjmp(( 或 siglongjmp(( 的信号都被阻止 在每次调用非异步信号安全函数期间,并且没有这样的 调用是在从对 main(( 的初始调用返回后进行的。

相关内容

  • 没有找到相关文章

最新更新