2016-03-08 51 views
1
#include <signal.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 

static jmp_buf env_alrm; 

static void sig_alarm(int signo) 
{ 
     longjmp(env_alrm, 1); 
} 
int sleep2(unsigned int seconds) 
{ 
     if(signal(SIGALRM, sig_alarm)==SIG_ERR) 
       return seconds; 

     if(setjmp(env_alrm)==0) //when it is first called, return value is 0 
     { 
       alarm(seconds); 
       pause(); 
     } 

     return (alarm(0)) 
}  

在這段代碼中,我認爲這是無限循環。我的想法如下:longjmp,setjmp的無限循環

我們打電話sleep2()主要功能如sleep2(3),然後在打電話pause()後,SIGALRM將在3秒後交付。所以,信號處理程序sig_alarm()將被調用。

而且,在調用longjmp()後,它將轉到setjmp()函數sleep2。最後,在測試setjmp()的返回值(調用longjmp()後應爲1)後,它將執行return alarm(0)。因此,它會立即再次呼叫sig_alarm()(因爲SIGALRM再次被傳送),並且此循環將繼續。

我錯過了什麼?

+0

在信號處理程序中使用'siglongjmp'。但是先閱讀[signal(7)](http://man7.org/linux/man-pages/man7/signal.7.html)首先要明白你不應該。 –

+1

報警結果是剩餘秒數。如果有0秒重新映射,只需返回0而不是報警(0)。 – cup

回答

2

alarm(0)不發送任何報警事件。它取消先前預定的警報並返回剩餘的秒數,直到取消警報(如果有)。

代碼的最後一行不會導致無限循環,因爲它不會執行sig_alarm。它會返回您的sleep2正常到期的剩餘秒數。在你的小例子中,這將是零。您的代碼可能是大型軟件的一部分,其中longjmp(和sleep2的最後一行)可能在計時器到期之前執行。在這種情況下,sleep2將剩餘的秒數返回到正常到期。