sigaction&x27;子进程中未调用s信号处理程序
我有一个程序,它为sigaction&x27;子进程中未调用s信号处理程序,c,linux,signals,sigaction,C,Linux,Signals,Sigaction,我有一个程序,它为SIGSEGV安装一个信号处理程序。在信号处理器中(我试图捕捉崩溃),我重新启动我的应用程序 但是,当我的应用程序重新启动时,它不再处理SIGSEGV 下面是一个例子: #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> const char * app = 0; void sig_handler(int signo) {
SIGSEGV
安装一个信号处理程序。在信号处理器中(我试图捕捉崩溃),我重新启动我的应用程序
但是,当我的应用程序重新启动时,它不再处理SIGSEGV
下面是一个例子:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
const char * app = 0;
void sig_handler(int signo)
{
puts("sig_handler");
const pid_t p = fork();
if (p == 0)
{
printf("Running app %s\n", app);
execl(app, 0);
}
exit(1);
}
int main(int argc, char** argv)
{
app = argv[0];
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_handler = sig_handler;
act.sa_flags = 0;
const int status = sigaction(SIGSEGV, &act, 0) == 0;
printf("signaction = %d\n", status);
sleep(5);
int* a = 0;
int b = *a;
return 0;
}
所以我可以看出sighandler的设置是正确的,但复活的应用程序只是静静地崩溃了
我遗漏了什么?您遗漏的是,默认情况下,当您处理信号时,该信号的任何附加传递都会被阻止,直到处理功能返回。由于您从未从信号处理程序返回(而是调用
execl()
),因此您的第二个SIGSEGV
没有被传递。它一直在等待信号处理函数返回,但它永远不会返回
要获得您想要的结果,您必须更改此默认行为。最简单的方法是在注册信号处理程序时设置适当的标志:
act.sa_flags = SA_NODEFER;
你会得到你想要的递归行为。您的另一个选项是在调用execl()
之前,使用sigprocmask()
解除对其的阻止
其他几个辅助点:
put()
、printf()
、execl()
和exit()
不是异步安全的,不应从信号处理程序调用execle()
和\u exit()
就可以了execl()
。第一个参数应该是应用程序名,所以execl(app,app,(char*)0)代码>将是正确的。您省略的对char*
的强制转换是必需的
请注意,规范说明挂起的信号由子进程继承。也有关于信号处理程序重置为默认值的规则。这是一个密集的阅读-页面中有很多信息。@JonathanLeffler我被
fork
的手册弄糊涂了,在那里你可以找到:孩子的一组待决信号最初是空的
@MichałWalenciak:它最初必须是空的,真的,因为这是一个全新的过程,还没有人向它发送任何信号。@MichałWalenciak:afork()
,这是真的;但是您的代码中没有fork()
;您只需使用execl()
来运行新的可执行文件,而且(让我有点惊讶的是)我没有看到任何迹象表明在执行新程序(或当前程序的新副本)时会删除挂起的信号。我可能错过了相关信息。@JonathanLeffler:我有叉子;)
act.sa_flags = SA_NODEFER;