2011-06-13 63 views
2

this paragraph,下面有問題:什麼是暫停()的問題?

/* usr_interrupt is set by the signal handler. */ 
if (!usr_interrupt) 
    pause(); 

/* Do work once the signal arrives. */ 
... 

並應使用sigsuspend代替。

但我還沒有看到這個問題是pause什麼,以及如何解決sigsuspend它,

任何人都可以更詳細解釋一下嗎?

回答

2

讓我們看看會發生什麼,當信號到達您之前已經檢查usr_interrupt後打電話pause

 
main thread       signal handler 
-----------       -------------- 
if (!usr_interrupt) 
// this is true      // signal kicks up handler 
             usr_interrupt = 1; 
             // handler finishes 
pause(); 
// will wait for signal 

你可以,你已經錯過了信號的情況下看到的。非常重要的是,如果沒有進一步的信號傳入,因爲你的程序將會從永遠不會動作。這就是所謂的競賽條件。現在讓我們看看與sigsuspend會發生什麼:

 
main thread       signal handler 
-----------       -------------- 
// set up to delay signal. 
sigemptyset (&mask); 
sigaddset (&mask, SIGUSR1); 

// this will delay (block) signal. 
// possibly do this first if USR1 
// may be blocked already (check!): 
// sigprocmask (SIG_UNBLOCK, &mask, &old); 
sigprocmask (SIG_BLOCK, &mask, &old); 

if (!usr_interrupt) 
             // signal arrives, delayed. 
// unblock signal/wait (atomically). 
sigsuspend (&old); 
             // delayed handler start. 
             usr_interrupt = 1; 
             // handler finishes. 
// sigsuspend returns, clean up. 
sigprocmask (SIG_UNBLOCK, &mask, NULL); 

在這種情況下,沒有競爭條件,因爲信號被延遲,直到主線程是準備好了。

+0

如果信號也被「老」封鎖了怎麼辦? – wireshark 2011-06-13 08:51:01

+0

@wireshark:如果你設置不正確,那麼它將無法工作。但是對於所有事情都是如此,所以我不確定你的觀點是什麼。如果您想確保設置正確,請先解鎖USR1。 – paxdiablo 2011-06-13 08:54:05

+0

你知道gdb的內部信號處理嗎?希望你知道我以前的問題的答案? http://stackoverflow.com/questions/6301130/sigint-not-trapped-while-debugging-nginx-with-gdb – wireshark 2011-06-13 09:00:16

0

這是一個典型的競賽條件。

 
Main    | Signal handler 
--------------------|----------------------- 
// at this point, | 
// no signal has | 
// arrived, so we | 
// enter the if  | 
        | 
if (!usr_interrupt) | 
        | {signal arrives...} 
        | usr_interrupt = 1; 
        | {...handler finishes} 
pause();   | 
        | 
// uh-oh, we missed | 
// the signal!  | 

即日起至下一個信號到達pause()不會得到暢通(這取決於程序可能永遠不會發生)。