关于捕获Unix信号的问题

时间:2011-05-26 16:23:01

标签: unix signals

以下代码仅捕获“SIGINT”信号一次然后中断(程序存在):

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

void IntHandler(int value);

void CatchIntSignal()
{
    struct sigaction intAction;
    intAction.sa_handler = IntHandler;
    sigemptyset(&intAction.sa_mask);
    intAction.sa_flags = 0;
    //if to uncomment any of "0" or "SIG_IGN" - IntHandler will be never called:
    //intAction.sa_sigaction = 0/*SIG_IGN*/;
    if(sigaction(SIGINT, &intAction, NULL) != 0)
    {
        printf("sigaction() failed.\n");
    }
}

void IntHandler(int value)
{
    printf("IntHandler(%d)\n", value);
    //uncommenting this does not help:
    //CatchIntSignal();
}

int main()
{
    CatchIntSignal();
    getchar();
    return 0;
}

如何修改此代码以在SIGINT捕获后保留程序的退出? 如果将 intAction.sa_sigaction 设置为0或SIG_IGN - 永远不会调用IntHandler - 但为什么呢?哪个未定义的值必须说系统“必须调用IntHandler”?如果我将一些处理程序设置为 intAction.sa_sigaction - 将调用此处理程序(但IntHandler不会)。系统如何知道我确实设置了 intAction.sa_sigaction

3 个答案:

答案 0 :(得分:4)

您的问题是sa_handler的{​​{1}}和sa_sigaction字段实际上是相同的字段。引用struct sigaction :( / p>)的(OSX)联机帮助页

sigaction(2)

因此,您对 struct sigaction { union __sigaction_u __sigaction_u; /* signal handler */ sigset_t sa_mask; /* signal mask to apply */ int sa_flags; /* see signal options below */ }; union __sigaction_u { void (*__sa_handler)(int); void (*__sa_sigaction)(int, struct __siginfo *, void *); }; #define sa_handler __sigaction_u.__sa_handler #define sa_sigaction __sigaction_u.__sa_sigaction 的分配将覆盖您已设置的处理程序。您应该设置sa_sigaction并单独留下sa_handler。这就是sa_sigaction应该阅读的内容:

CatchIntSignal

(您可能需要添加void CatchIntSignal() { struct sigaction intAction; intAction.sa_handler = IntHandler; sigemptyset(&intAction.sa_mask); intAction.sa_flags = SA_RESTART; if(sigaction(SIGINT, &intAction, NULL) != 0) printf("sigaction() failed: %s\n", strerror(errno)); } string.h的#includes以获取errno.h位进行编译。在系统调用失败时触发的错误消息中始终包含strerror(errno) 。)

(更正:将strerror(errno)添加到每个ninjalj的标记。)

答案 1 :(得分:2)

您的麻烦可能是系统调用被中断,因此getchar()返回,可能是EOF。该计划的下一步是退出...

因此,您可以尝试检查getchar()返回的内容,重置stdin上的错误状态,然后再次致电getchar()以获取下一个信号。

答案 2 :(得分:0)

捕获中断信号并在捕获代码中处理后,需要将处理设置回SIG_DFL

编辑:请忽略。这仅适用于旧的unix信号()。