为什么SIGALRM第二次不工作?

时间:2016-08-09 05:48:02

标签: c system-calls

#include<stdio.h>
#include<setjmp.h>
#include<signal.h>

jmp_buf  env;

void alarmHandler()
    {
        printf("\n in alarm Handle");

        longjmp(env,1);
    }



int main()
    {
        signal(SIGALRM,alarmHandler);

        alarm(2);

    for(;;)
    {
        printf("\nhello");
        sleep(1);

        if(setjmp(env))
            {

                printf("\n inside if");
                signal(SIGALRM,alarmHandler);
                alarm(2);
            }

    }


return 0;

    }

启动时,激活状态监视信号,然后激活警报2秒(倒计时)。 在for循环内部,每次使用setjmp(env)时,setjmp(env)会随着时间的推移保存longjmp() setjmp()。 默认情况下,longjmp()如果从<all> <one>Something 1</one> <two>something 2</two> <check> <present>true</present> </check> <action> <perform></perform> </action> </all> 调用则返回0,无论第二个arg值是该值返回。

2 个答案:

答案 0 :(得分:4)

longjmp函数不被视为调用信号处理程序的安全函数。

通过跳跃,你永远不会离开信号处理程序,进程的上下文仍将是信号处理程序的上下文。那么当我们还没有离开第一个信号处理器时,怎么能调用另一个信号处理程序呢?这就是为什么你不应该做你做的事情。

而是在信号处理程序中设置一个标志,然后在循环中轮询该标志。然后正常从信号处理程序返回,让进程继续正常进行。

答案 1 :(得分:2)

我使用GCC 6.1.0在Mac OS X 10.11.6上运行此代码,但有很多事情可能阻止它在其他地方工作。除此之外,POSIX并未指定siglongjmp()strlen()在信号处理程序中使用是安全的(请参阅POSIX ViewChanged)。您不应在信号处理程序中使用Signal Concepts - 或signal()

我的默认编译选项要求警报处理程序在定义之前是静态的或声明的;该参数是必要的,以避免传递给longjmp(env, signum)的指针类型不匹配;需要使用信号编号(但我可以使用#include <stdio.h> #include <setjmp.h> #include <signal.h> #include <unistd.h> jmp_buf env; static void alarmHandler(int signum) { printf("\nin alarm Handle (%d)\n", signum); longjmp(env, 1); } int main(void) { signal(SIGALRM, alarmHandler); alarm(2); for ( ; ; ) { printf("\nhello"); sleep(1); if (setjmp(env)) { printf("\ninside if\n"); signal(SIGALRM, alarmHandler); alarm(2); } } printf("Exiting\n"); return 0; } 来执行此操作)。

但是,你经常可以放弃滥用规则。

hello
hello
in alarm Handle (14)

inside if

hello
hello
in alarm Handle (14)

inside if

hello
hello
in alarm Handle (14)

inside if

hello
hello
in alarm Handle (14)

示例输出:

printf()

我感到无聊并且在那时打断了它。

我不确定在{{1}}语句之后添加换行符是否足以使其正常工作。