下面的代码在第二个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;
}

最佳答案

setjmplongjmp不一定恢复信号屏蔽(取决于实现)可能发生的情况是在处理第一个SIGSEGV之后,信号掩码恢复为默认值因此,第二个错误没有被捕获,也就是说,默认操作代替了你的动作,即退出进程。
你应该改用sigsetjmpsiglongjmp
POSIX状态:
未指定longjmp()是还原信号掩码、保持信号掩码不变,还是还原为调用setjmp()时的值。
并建议:
其行为取决于信号掩码值的应用程序
不应使用longjmp()和setjmp(),因为它们对
未指定信号掩码,但应改为使用siglongjmp()
和sigsetjmp()函数(可以保存和恢复信号掩码
在应用程序控制下)。
此外,跳出信号处理程序也有一些限制:
建议应用程序不要调用longjmp()或
来自信号处理程序的siglongjmp()避免未定义的行为
从信号处理程序调用这些函数时,应用程序需要
确保以下两点之一:
在调用longjmp()或siglongjmp()之后,进程只调用
异步信号安全函数,不从初始调用返回
到main()。
处理程序调用longjmp()或siglongjmp()的任何信号都被阻止
每次调用非异步信号安全函数时
调用是在从初始调用返回到main()之后进行的。

关于c - SIGSEGV不能两次被抓获,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51765041/

10-11 21:13