以下代码在第二个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 ("%s\n", 2); // This will segfault
res = 0;
}
// try to catch second segmentation fault
if (setjmp(escapeCallJmpBuf)) {
res = 2;
} else {
printf ("%s\n", 3); // This will segfault
res = 0;
}
sigaction(SIGSEGV, &segvActionOld, 0);
return res;
}
答案 0 :(得分:1)
setjmp
和longjmp
不一定恢复信号掩码(取决于实现方式)。可能发生的情况是在处理完第一个SIGSEGV之后,信号掩码恢复为默认值。因此第二个SIGSEGV未被捕获,即,默认操作代替您的默认操作发生,该操作将退出该过程。
您应该改用sigsetjmp
和siglongjmp
。
POSIX状态:
不确定longjmp()是恢复信号掩码,保持信号掩码不变还是将其恢复为调用setjmp()时的值。
并建议:
其行为取决于信号掩码值的应用程序 不应使用longjmp()和setjmp(),因为它们对 信号掩码未指定,但应使用siglongjmp() 和sigsetjmp()函数(可以保存和恢复信号掩码 在应用程序的控制之下)。
此外,从信号处理程序跳转还存在一些限制:
建议应用程序不要调用longjmp()或 信号处理程序中的siglongjmp()。为了避免未定义的行为,当 从信号处理程序调用这些函数,应用程序需要 确保以下两件事之一:
在调用longjmp()或siglongjmp()之后,该过程仅调用 异步信号安全功能,不会从初始调用返回 到main()。
其处理程序调用longjmp()或siglongjmp()的任何信号均被阻止 在每次对非异步信号安全函数的调用期间,都没有这样的情况 从初始调用返回到main()之后进行调用。