且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如果我捕捉到SIGSEGV,并且信号处理程序导致了另一个SIGSEGV,会发生什么?

更新时间:2022-06-15 08:55:06

默认情况下,正在处理信号时将其屏蔽,因此无法递归触发它.如果屏蔽信号是由程序执行触发的(无效的内存访问,segfault,除以0等),则该行为是不确定的:

By default, while signal is being handled it is masked, so it can't be triggered recursively. If masked signal is triggered by program execution (invalid memory access, segfault, division by 0 etc.), the behavior is undefined:

如果在生成SIGBUS,SIGFPE,SIGILL或SIGSEGV的同时阻止,结果是不确定的,除非信号是由kill(2),sigqueue(3)或raise(3).

If SIGBUS, SIGFPE, SIGILL, or SIGSEGV are generated while they are blocked, the result is undefined, unless the signal was generated by kill(2), sigqueue(3), or raise(3).

在我的系统上,它导致进程崩溃.

On my system, it causes process to crash.

使用 SA_NODEFER 没有屏蔽,因此可以递归处理信号,直到堆栈溢出为止.添加 SA_RESETHAND 将恢复默认操作(SIGSEGV崩溃).

With SA_NODEFER there is no masking, so signal can be handled recursively until stack overflows. And adding SA_RESETHAND would restore default action (crash for SIGSEGV).

我将您的示例改编为简单的测试程序,因此您可以验证此行为:

I adapted your example to simple testing program, so you can verify this behavior:

#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

volatile char *ptr;

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. */
  write(1, "11\n", 3);
  *ptr = 1;
  write(1, "13\n", 3);
  abort(); /* This should give us the expected core dump (if we survive to this point) */
}

struct sigaction sa = {}; /* initialised to all zero (I vote for GCC style breach of standard here) */

int main()
{
  sa.sa_handler = DisasterSignals;
  sa.sa_flags = /*SA_RESETHAND | */SA_NODEFER;  /* To have or have not */
  sigaction(SIGSEGV, &sa, NULL);

  write(1, "25\n", 3);
  *ptr = 1;
}