longjmp,setjmp的无限循环

时间:2016-03-08 06:15:11

标签: c linux signals

#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))
}       

在这段代码中,我认为这是无限循环。我的想法如下:

我们在sleep2()之内调用sleep2(3)个函数,然后在调用pause()后,SIGALRM将在3秒后发送。因此,将调用信号处理程序sig_alarm()

并且,在调用longjmp()之后,它将转到sleep2中的setjmp()函数。最后,在测试setjmp()的返回值(调用longjmp()后应为1)后,它将执行return alarm(0)。因此,它会立即再次调用sig_alarm()(因为SIGALRM再次传递),并且此循环将继续。

我错过了什么?

1 个答案:

答案 0 :(得分:2)

alarm(0)不会发送任何警报事件。它取消先前安排的警报并返回此取消警报之前剩余的秒数(如果有)。

代码的最后一行不会导致无限循环,因为它不会执行sig_alarm。它会将剩余的秒数返回到sleep2的正常到期时间。在你的小例子中,这将是零。您的代码可能是较大软件的一部分,其中longjmp(以及sleep2的最后一行)可能在计时器到期之前执行。在这种情况下,sleep2会返回正常到期的剩余秒数。