【问题标题】:Double signal send with command timeout带有命令超时的双信号发送
【发布时间】:2021-03-07 15:17:12
【问题描述】:

我目前正在从事一个需要管理信号的项目。 我目前正在使用此代码

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

void gest_sig_int(int signo) {
    write(1, "I receive a signal\n", 19);
}

int     main(void) {
    struct sigaction s;

    s.sa_handler = gest_sig_int;
    s.sa_flags = 0;
    sigemptyset(&s.sa_mask);
    sigaction(SIGINT , &s, NULL);
    while (1);
    return (0);
}

我用编译

gcc test.c -o test

如果我执行代码并使用 CTRL + C 程序显示

./test
^CI receive a signal

这正是我想要的结果!

但是当我尝试用 timeout 命令做同样的事情时,我的程序会收到两次信号

timeout -s INT 2 ./test
I receive a signal
I receive a signal

不知道是来自我的程序还是命令timeout

感谢阅读!

【问题讨论】:

  • printf 不是异步信号安全的。从信号处理程序调用它会产生未定义的行为。
  • 即使我使用 write 而不是 printf 输出也是完全一样的
  • 然后更新问题以呈现具有明确行为的代码会改进它。但这里更大的信息是不要从信号处理程序调用printf。不要认为它没问题,即使它似乎在任何给定情况下都有你期望的结果。我见过失败的案例,而让自己接受这种失败是一个糟糕的策略。
  • 好的,感谢我编辑帖子的信息
  • 无法重现。 timeout 只发送一个信号,我只看到程序的一行输出。

标签: c signals


【解决方案1】:

但是当我尝试用 timeout 命令做同样的事情时,我的 程序接收信号两次

我可以使用 GNU coreutils 8.25 中包含的 timeout 命令重现您的问题。

不知道是来自我的程序还是命令timeout

我看不出有任何理由认为这是你的程序,如果我对 timeout 命令使用不同的变体,我可以观察到不同的行为:

> timeout -k 1 -s INT 2 ./test
I receive a signal
Killed
>

-k 1 指示 timeout 如果在接收到第一个信号后一秒内没有终止,则向孩子发送 SIGKILL。这样,测试程序的信号处理程序(仅为SIGINT 注册)只会触发一次,无论为终止超时指定多长时间。

当未指定-k 选项时,观察到此版本timeout 的行为似乎是发送相同类型的第二个信号,如果子级未在第一个信号后的亚秒延迟内终止.确实,我认为这是通过您的实验确定的,尽管我没有发现它的记录。

【讨论】:

  • 谢谢!你说的对 !如果程序在第一个信号之后没有退出,那么超时命令发送显然不是来自我的函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 1970-01-01
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 2013-12-05
  • 1970-01-01
相关资源
最近更新 更多