2014-06-05 33 views
3

下面是abort功能實現的示例,使用signals,如「Unix中的高級編程」中所述。很少有疑慮在下面的代碼 -使用信號中止功能實現


void abort(void)   /* POSIX-style abort() function */ 
{ 
    sigset_t   mask; 
    struct sigaction action; 

    /* 
    * Caller can't ignore SIGABRT, if so reset to default. 
    */ 
    sigaction(SIGABRT, NULL, &action); 
    if (action.sa_handler == SIG_IGN) { 
     action.sa_handler = SIG_DFL; 
     sigaction(SIGABRT, &action, NULL); 
    } 
    if (action.sa_handler == SIG_DFL) 
     fflush(NULL);   /* flush all open stdio streams */ 

    /* 
    * Caller can't block SIGABRT; make sure it's unblocked. 
    */ 
    sigfillset(&mask); 
    sigdelset(&mask, SIGABRT); /* mask has only SIGABRT turned off */ 
    sigprocmask(SIG_SETMASK, &mask, NULL); 
    kill(getpid(), SIGABRT); /* send the signal */ **STEP 1** 

    /* 
    * If we're here, process caught SIGABRT and returned. 
    */ 
    fflush(NULL);    /* flush all open stdio streams */ 
    action.sa_handler = SIG_DFL; 
    sigaction(SIGABRT, &action, NULL); /* reset to default */ 
    sigprocmask(SIG_SETMASK, &mask, NULL); /* just in case ... */ 
    kill(getpid(), SIGABRT);    /* and one more time */ **STEP 2** 
    exit(1); /* this should never be executed ... */ 
} 

問題
一個。當我們發送第一個killSIGABRT(由步驟1標記)時,爲什麼我們期待代碼繼續到下一行? (請參閱註釋 - '如果我們在這裏,過程捕獲了SIGABRT並返回')

b。爲什麼我們需要再次發送kill信號(在步驟2中),然後exit(1)不應該被擊中。 (請參閱代碼中的註釋)

+0

關於b)我認爲你可能會收到原作者更好的答案。它可能只是「地獄只是凍結」/「以防萬一」的東西。 –

回答

5

大多數程序都不會對SIGABRT做任何特別的操作。

但是一些奇怪的程序可能會在SIGABRT上安裝它們自己的信號處理程序,並且abort函數應該仍然可以工作,即使對它們也是如此。

所以大多數程序-those不要再追SIGABRT - 不會走過去的第1步(因爲SIGABRT的默認行爲是轉儲核心,根據signal(7) ...)。

幾個程序誰抓到SIGABRT將前往第2步(如果撥打電話abort)。此時,SIGABRT的默認行爲已重新安裝。所以程序轉儲核心在第2步。最後的exit(1)無法到達。

+0

你的是完整的。我實際上錯過了重新安裝默認處理程序。刪除我的答案:) –