Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如果我捕捉到SIGSEGV并且信号处理程序导致另一个SIGSEGV,会发生什么?_C_Linux - Fatal编程技术网

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

C 如果我捕捉到SIGSEGV并且信号处理程序导致另一个SIGSEGV,会发生什么?,c,linux,C,Linux,这个问题是在考虑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_hand

这个问题是在考虑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|u RESETHAND | SA|u NODEFER
:这似乎将系统置于逻辑陷阱:在“Q”处,应生成SIGSEGV。但是SIGSEGV在信号处理程序中被阻塞(默认sigaction行为)。如何继续执行?会结冰吗?它会跳过令人不快的指令吗(我想不会)

2) 使用
SA|u RESETHAND | SA|u NODEFER
:我猜在这种情况下,当SIGSEGV重复时,程序将以“正常”方式崩溃


3) 仅使用
SA_NODEFER
:我猜在这种情况下,当重复SIGSEGV时,会递归调用信号处理程序;如果SIGSEGV总是重复,我们会得到一个冻结,直到堆栈溢出,然后发生什么。

默认情况下,在处理信号时,它被屏蔽,因此不能递归触发。如果屏蔽信号由程序执行触发(无效内存访问、segfault、除法0等),则行为未定义:

如果在运行时生成了SIGBUS、SIGFPE、SIGILL或SIGSEGV 阻塞,结果未定义,除非信号由 终止(2)、信号队列(3)或提升(3)

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

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

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

#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;
}
#包括
#包括
#包括
#包括
挥发性炭*ptr;
静态无效解除信号(int信号)
{
/*我们无法挽救局面,捕捉信号的目的是
只是在我们开始之前做一些聪明的事情来帮助调试*/
写(1,“11\n”,3);
*ptr=1;
写(1,“13\n”,3);
abort();/*这将为我们提供预期的内核转储(如果我们能够生存到这一点)*/
}
结构sigaction sa={};/*初始化为零(我在这里投票赞成GCC风格违反标准)*/
int main()
{
sa.sa_handler=灾难信号;
sa.sa_flags=/*sa_RESETHAND |*/sa_NODEFER;/*是否有*/
sigaction(SIGSEGV,&sa,NULL);
写(1,“25\n”,3);
*ptr=1;
}

Quis custodiet ipsos custodes?您应该只调用信号处理程序中的可重入函数。我的结果显示:处理器中的1和2-segfault会立即使程序崩溃。3-信号处理程序递归约13k次(变化),然后崩溃。-逻辑陷阱的答案:“如果SIGBUS、SIGFPE、SIGILL或SIGSEGV在阻塞时生成,则结果未定义,除非信号是由kill(2)、sigqueue(3)或raise(3)生成的。”您不能将注释标记为已接受的答案,但可以标记答案。