sigaction 的信号处理程序未在子进程中调用
sigaction's signal handler not called in child process
我有一个程序,它为 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;
}
我得到的输出是:
./signals
signaction = 1
sig_handler
Running app ./signals
signaction = 1
所以我可以看到 sighandler 设置正确,但复活的应用程序只是无声地崩溃了。
我错过了什么?
您缺少的是,默认情况下,当您处理信号时,该信号的任何额外传送都将被阻止,直到处理函数 returns。由于您从不从信号处理程序 return (而是调用 execl()
),因此您的第二个 SIGSEGV
未被传送。它一直等到你的信号处理函数 returns,它永远不会。
要获得您似乎想要的结果,您必须更改此默认行为。最简单的方法是在注册信号处理程序时设置适当的标志:
act.sa_flags = SA_NODEFER;
您将获得您似乎正在寻找的递归行为。您的另一个选择是在您的 execl()
调用之前使用 sigprocmask()
解锁它。
几个其他辅助要点:
puts()
、printf()
、execl()
和 exit()
不是异步安全的,不应从信号处理程序调用。 execle()
和 _exit()
都可以。
您没有正确调用 execl()
。第一个参数应该是应用程序名称,因此 execl(app, app, (char *)0);
是正确的。您省略的 char *
的强制转换是必需的。
我有一个程序,它为 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;
}
我得到的输出是:
./signals
signaction = 1
sig_handler
Running app ./signals
signaction = 1
所以我可以看到 sighandler 设置正确,但复活的应用程序只是无声地崩溃了。
我错过了什么?
您缺少的是,默认情况下,当您处理信号时,该信号的任何额外传送都将被阻止,直到处理函数 returns。由于您从不从信号处理程序 return (而是调用 execl()
),因此您的第二个 SIGSEGV
未被传送。它一直等到你的信号处理函数 returns,它永远不会。
要获得您似乎想要的结果,您必须更改此默认行为。最简单的方法是在注册信号处理程序时设置适当的标志:
act.sa_flags = SA_NODEFER;
您将获得您似乎正在寻找的递归行为。您的另一个选择是在您的 execl()
调用之前使用 sigprocmask()
解锁它。
几个其他辅助要点:
puts()
、printf()
、execl()
和exit()
不是异步安全的,不应从信号处理程序调用。execle()
和_exit()
都可以。您没有正确调用
execl()
。第一个参数应该是应用程序名称,因此execl(app, app, (char *)0);
是正确的。您省略的char *
的强制转换是必需的。