【问题标题】:sigaction is catching signal only oncesigaction 只捕获一次信号
【发布时间】:2021-03-24 12:30:32
【问题描述】:

考虑以下代码:

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

    void catch ()
    {
        printf("hi\n");
    }
    int main()
    {
        struct sigaction act;
        act.sa_handler = catch;
        sigaction(SIGINT, &act, NULL);
        for(;;);
        return 0;
    }

当这个程序运行时。我第一次按 CTRL-C 时会打印“hi”。
但第二次程序退出。这可能是什么原因?
我想要的是程序在每次发出信号时都会捕获它。

【问题讨论】:

  • 附带说明,您不应该从信号处理程序调用printf,因为它不能保证是信号安全函数。见the signal-safety(7) man page
  • 您没有正确初始化结构。您还需要设置标志和掩码。

标签: c linux signals signal-handling sigaction


【解决方案1】:

如果你不使用任何 SA_FLAG 来明确定义“第一次捕获信号后要做什么”的行为,它应该可以工作。

清除sigaction的内容,然后初始化。

memset(&act,0,sizeof(act)); // clear contents first
act.sa_handler = catch;
sigaction(SIGINT, &act, NULL);

见,sigaction(2)

此外,正如 Daniel 指出的那样,不要在信号处理程序中使用 printf。见 signal-safety(7)

如果你想打印一些东西,或者只是在你的信号处理程序中做一些事情,你必须使用 signal-safe 函数。在您的情况下,您可以使用 write() 系统调用,而不是使用 printf。见write(2)

作者,

write(1,"hi\n",3); // 1 means standard out.

【讨论】:

  • 那么如果 printf 不安全,有没有其他方法可以从信号处理程序内部打印一些文本?将此代码 memset 工作。是不是就像一旦生成了信号,我们就需要清除 sigaction 才能让它再次工作。这个清算的事情记录在哪里?手册页中有吗
  • 从信号处理程序调用write会覆盖errno,破坏错误处理代码
  • @StaceyGirl 好点。信号处理程序必须做一些基本的事情,而不是做复杂的 I/O 操作。
  • sigaction(SIGINT, &amp;act, NULL);这个初始化完成了吗?正如乔纳森所说,这不是初始化的正确方法
  • @aharani 如果你不想要任何特殊的东西,比如新的信号掩码,你可以使用这个初始化步骤。通过这种方式,您的处理程序将具有默认行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多