簡體   English   中英

在子進程中沒有調用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以正確的方式設置,但復活的應用程序只是默默地崩潰。

我錯過了什么?

您缺少的是,默認情況下,當您處理信號時,該信號的任何其他傳送都將被阻止,直到處理函數返回為止。 因為你永遠不會從你的信號處理程序返回(你調用execl() )然后你的第二個SIGSEGV沒有交付。 它等待你的信號處理函數返回,它永遠不會。

要獲得您想要的結果,您必須更改此默認行為。 最簡單的方法是在注冊信號處理程序時設置適當的標志:

act.sa_flags = SA_NODEFER;

你會得到你似乎在尋找的遞歸行為。 您的另一個選擇是在execl()調用之前使用sigprocmask()取消阻止它。

幾個其他輔助點:

  1. puts()printf()execl()exit()不是異步安全的,不應該從信號處理程序中調用。 execle()_exit()就可以了。

  2. 你沒有正確地調用execl() 第一個參數應該是應用程序名稱,所以execl(app, app, (char *)0); 會是對的。 您省略的轉換為char *是必需的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM