gpt4 book ai didi

c - sigaction 的信号处理程序未在子进程中调用

转载 作者:太空狗 更新时间:2023-10-29 11:03:47 25 4
gpt4 key购买 nike

我有一个程序,它为 SIGSEGV 安装信号处理程序。在信号处理程序中(我 try catch 崩溃)我重新启动我的应用程序。

但是当我的应用程序复活时,它不再处理 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;
}

我得到的输出是:

./signals 
signaction = 1
sig_handler
Running app ./signals
signaction = 1

所以我可以看到 sighandler 以正确的方式设置,但复活的应用程序只是默默地崩溃了。

我错过了什么?

最佳答案

您缺少的是,默认情况下,当您处理信号时,该信号的任何额外传递都将被阻止,直到处理函数返回。由于您永远不会从信号处理程序返回(而是调用 execl()),因此您的第二个 SIGSEGV 不会被传送。它会一直等到您的信号处理函数返回,但它永远不会返回。

要获得您似乎想要的结果,您必须更改此默认行为。最简单的方法是在注册信号处理程序时设置适当的标志:

act.sa_flags = SA_NODEFER;

您将获得您似乎正在寻找的递归行为。您的另一个选择是在您的 execl() 调用之前使用 sigprocmask() 解除阻止。

其他一些辅助点:

  1. puts()printf()execl()exit() 是不是异步安全的,不应从信号处理程序中调用。 execle()_exit() 就可以了。

  2. 您没有正确调用 execl()。第一个参数应该是应用程序名称,所以 execl(app, app, (char *)0); 是正确的。需要强制转换为您省略的 char *

关于c - sigaction 的信号处理程序未在子进程中调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35976496/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com