[英]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以正確的方式設置,但復活的應用程序只是默默地崩潰。
我錯過了什么?
您缺少的是,默認情況下,當您處理信號時,該信號的任何其他傳送都將被阻止,直到處理函數返回為止。 因為你永遠不會從你的信號處理程序返回(你調用execl()
)然后你的第二個SIGSEGV
沒有交付。 它等待你的信號處理函數返回,它永遠不會。
要獲得您想要的結果,您必須更改此默認行為。 最簡單的方法是在注冊信號處理程序時設置適當的標志:
act.sa_flags = SA_NODEFER;
你會得到你似乎在尋找的遞歸行為。 您的另一個選擇是在execl()
調用之前使用sigprocmask()
取消阻止它。
幾個其他輔助點:
puts()
, printf()
, execl()
和exit()
不是異步安全的,不應該從信號處理程序中調用。 execle()
和_exit()
就可以了。
你沒有正確地調用execl()
。 第一個參數應該是應用程序名稱,所以execl(app, app, (char *)0);
會是對的。 您省略的轉換為char *
是必需的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.