【问题标题】:Why my Linux signal handler has no reaction to the signal?为什么我的 Linux 信号处理程序对信号没有反应?
【发布时间】:2013-05-12 09:32:59
【问题描述】:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

static void pr_mask(const char * string) {
    sigset_t procmask;

    sigprocmask(SIG_SETMASK, NULL, &procmask);

    printf("%s: ", string);
    if(sigismember(&procmask, SIGINT))
        printf("SIGINT ");
    if(sigismember(&procmask, SIGUSR1))
        printf("SIGUSR1 ");
    if(sigismember(&procmask, SIGUSR2))
        printf("SIGUSR2 ");
    if(sigismember(&procmask, SIGTERM))
        printf("SIGTERM ");
    if(sigismember(&procmask, SIGQUIT))
        printf("SIGQUIT ");
    printf("/n");
}

static void sigusr(int signum)
{
    pr_mask("int sigusr");

    if(signum == SIGUSR1)
        printf("SIGUSR1 received/n");
    else if(signum == SIGUSR2)
        printf("SIGUSR2 received/n");
    else
        printf("signal %d received/n", signum);
}

int main(void)
{
    if(signal(SIGUSR1, sigusr) == SIG_ERR) {
        printf("error catching SIGUSR1/n");
        exit(1);
    }

    if(signal(SIGUSR2, SIG_IGN) == SIG_ERR) {
        printf("error ignoring SIGUSR2/n");
        exit(1);
    }

    if(signal(SIGINT, SIG_DFL) == SIG_ERR) {
        printf("error setting SIGINT to default/n");
        exit(1);
    }

    while(1)
        pause();

    exit(0);
}

对于上面的代码,在 Linux 中编译后,我开始像下面这样运行它。

tomxue@ubuntu:~$ ./a.out &
[2] 5554
[1]   Killed                  ./a.out
tomxue@ubuntu:~$ kill -USR1 5554
tomxue@ubuntu:~$ kill -USR2 5554
tomxue@ubuntu:~$ kill -9 5554
[2]+  Killed                  ./a.out

为什么我发出USR1和USR2信号时没有反应?

【问题讨论】:

  • printf("/n"); -->> printf("\n"); BTW:你不应该在信号处理程序中使用 printf()。
  • 代码是从某处复制的,我没有注意到“/n”。

标签: c linux signals


【解决方案1】:

正如许多评论和回复的那样,在printf 格式字符串中使用\n 而不是/n。或致电fflush(3),例如在您的printf 之后添加fflush(NULL);

但是,在信号处理程序中调用 printf 是错误的。请参阅signal(7),其中解释了异步信号安全功能printf 不是异步信号安全功能)。

在实践中,信号处理程序最好设置一些volatile sigatomic_t 标志,应该在代码中的一些重要位置进行测试。

如果使用一些事件循环,Qt 建议的一个技巧是在程序开头附近创建一些pipe(2),以在事件循环中轮询该管道 - 例如。通过在信号处理程序中使用poll(2)write(2) 进入该管道(write 是异步信号安全的!)。

另见this answer

【讨论】:

    【解决方案2】:

    您的信号处理工作正常。只是/n 不是换行符。因为您不打印新行,所以所有输出都保存在缓冲区中。当您使用 KILL 信号终止进程时,此缓冲区将被丢弃。

    【讨论】:

    • 其实这样的信号处理是错误的,因为printf不是异步信号安全的。见my reply
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    相关资源
    最近更新 更多