2014-05-05 19 views
1

我與UNIX系統下測試C程序調用:SIGINT只在孩子的過程中接收,如果抓明確

#include <unistd.h> 
#include <signal.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

void abide(int sig_num) { 
    printf("I, sleeper, will abide to this signal %d!\n", sig_num); 
    fflush(stdout); 
    exit(0); 
} 

void refuse(int sig_num) { 
    signal(SIGINT, refuse); 
    printf("I, sleeper, REFUSE this signal %d!\n", sig_num); 
    fflush(stdout); 
} 

int main(int argc, char *argv[]) { 
    if (argc > 1 && strcmp(argv[1], "refuse") == 0) { 
     signal(SIGINT, refuse); 
    } else if (argc > 1 && strcmp(argv[1], "deaf") == 0) { 
     printf("I, sleeper, have been made deaf...\n"); 
    } else { 
     signal(SIGINT, abide); 
    } 
    printf("I, sleeper, am now sleeping for 10s...\n"); 
    sleep(10); 
    printf("I, sleeper, has terminated normally.\n"); 
    return 0; 
} 

然後我有另一個程序,如同一個小的殼。在我的測試點上,它會分叉並使子程序執行上面的程序(使用適當的參數)。這個外殼也忽略Ctrl + C鍵通過使用

signal(SIGINT, SIG_IGN); 

結果命令如下:

MyShell> ./sleeper 
I, sleeper, am now sleeping for 10s... 
^CI, sleeper, will abide to this signal! 
MyShell> ./sleeper refuse 
I, sleeper, am now sleeping for 10s... 
^CI, sleeper, REFUSE this signal! 
I, sleeper, has terminated normally. 
MyShell> ./sleeper deaf 
I, sleeper, have been made deaf... 
I, sleeper, am now sleeping for 10s... 
^C^C^C^C <---- not terminating 

第一次運行似乎是正確的。第二個有點奇怪,因爲我們實際上忽略了信號,但程序終止。也許是因爲我們打電話sleep()這被打斷了。

但這是第三個讓我困惑的結果。在一個普通的shell程序終止,但在我的自定義shell中沒有任何反應。它繼續運行。睡眠者程序的默認信號處理程序(終止它)是否應該像abide()一樣執行?

感謝您的任何澄清!

+1

預計第一次運行的輸出是?你的'abide'函數調用'exit()',但是你仍然看到'main'的最後一個'printf'輸出? –

+0

我的不好。我錯誤地複製了輸出。我編輯了這篇文章。 – bombax

+0

你似乎剛剛編輯出來,這導致我認爲你給我們展示的不是*真實*控制檯輸出... –

回答

1

解決了它。問題有點微妙。在使用fork()後,子進程顯然會繼承其父節點的信號處理程序,即使您之後使用了系統調用exec()。所以sleeper的子進程正在使用忽略處理程序。解決的辦法是簡單地

signal(SIGINT, SIG_DFL)

調用之間

添加默認的處理程序fork()exec()

+2

這對我來說沒有意義。兒童不會通過'exec'繼承信號處理程序。在'exec'之後,原始文本段(即包含處理程序的代碼)被汽化,那麼繼承了什麼?處理程序的地址指向什麼?取而代之的是,'exec'在將處理程序重置爲其默認處置的任何信號後,OS執行的操作。所以我想我不明白你的問題或解決方案。你要留下什麼嗎? – Duck

+0

據我所知不是。如果我在調用exec之前明確地將信號處理程序重置爲默認值,而不是如果我不這樣做,它會按預期工作。我按照'uname'運行Linux 3.2.0-61-generic。我特別使用'execvp'。 – bombax

+0

我會建議加倍檢查。我懷疑你在某個地方有單獨的錯誤。也許重新發布有問題的所有代碼,父母和孩子的問題。 – Duck