2011-07-18 31 views
1

根據sigsuspend()的手冊頁,它將用第一個參數替換當前的信號掩碼組。在APUE中,我看到一個例子如下。代碼可能有點太長,但我不想錯過任何東西。sigsuspend(),替換set還是add?

int pr_mask(char *s) 
{ 
    sigset_t sigset; 

    sigprocmask(0, NULL, &sigset); 

    printf("%s: ", s); 

    if(sigismember(&sigset, SIGINT)) printf("SIGINT "); 
    if(sigismember(&sigset, SIGQUIT)) printf("SIGQUIT "); 
    if(sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 "); 
    if(sigismember(&sigset, SIGALRM)) printf("SIGALRM "); 
    /* ..... */ 

    printf("\n"); 
    return 0; 
} 

void sig_quit(int signo) 
{ 
    pr_mask("in sig quit"); 
} 

int main() 
{ 
    sigset_t new, old, tempset; 

    signal(SIGQUIT, sig_quit); 

    sigemptyset(&tempset); 
    sigaddset(&tempset, SIGINT); 

    sigemptyset(&new); 
    sigaddset(&new, SIGQUIT); 
    sigprocmask(SIG_BLOCK, &new, &old); 

    pr_mask("in critical section"); 
    /* critical section */ 

    sigsuspend(&tempset); 
    pr_mask("after return form sigsuspend"); 

    sigprocmask(SIG_UNBLOCK, &new, NULL); 
    pr_mask("program exit"); 

    return 0; 
} 

輸出是:

in critical section: SIGQUIT 
in sig quit: SIGINT SIGQUIT 
after return form sigsuspend: SIGQUIT 
program exit: 

問題是第二行。 SIGQUIT仍在信號掩碼組中。

它應該只有SIGINT,因爲sigsuspend已經用tempset取代了信號掩碼,它只設置爲SIGINT

回答

1

在執行SIGQUIT處理程序時,SIGQUIT本身被阻止。這是爲了避免再次進入由事故處理程序...

POSIX spec for sigaction(你真的應該使用的,而不是signal):

當信號由安裝在信號捕獲功能捕獲通過sigaction(),在信號捕獲函數的持續時間內計算並安裝一個新的信號掩碼(或直到對sigprocmask()或sigsuspend()進行調用)。該掩碼是通過取得當前信號掩碼和發送信號的sa_mask值的組合,並且除非設置了SA_NODEFER或SA_RESETHAND,然後包括正在傳送的信號。

POSIX spec for signal是有點不太具體:

當信號發生,並且FUNC指向一個函數,它是實現定義是否a的當量:

信號(sig,SIG_DFL);

被執行或實現阻止某些實現定義的信號集合(至少包括sig)發生,直到當前信號處理已完成。

因此,操作系統在信號處理功能期間簡單地將信號添加到掩碼是合法的,顯然這正是Linux所做的。

0

因爲在執行SIGQUIT處理程序時會輸出「in sig quit:SIGINT SIGQUIT」,所以會將SIGQUIT添加到信號掩碼,這意味着當前掩碼將成爲tempset和SIGQUIT的並集。