【问题标题】:Ignoring signal if it's sent too quickly如果发送太快则忽略信号
【发布时间】:2021-03-11 16:28:23
【问题描述】:

我有以下代码:

//includes...

#define SIG_INT 0

//prints out <Text> when SIG_INT is received from siginfo_t*
void handler(int, siginfo_t*, void*);

int main()
{
    pid_t ambulance1 = 0;
    pid_t ambulance2 = 0;

    struct sigaction sigact;
    sigact.sa_sigaction = handler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = SA_SIGINFO;
    sigaction(SIGUSR1, &sigact, NULL);

    ambulance1 = fork();
    if(ambulance1 > 0) {
        ambulance2 = fork();
        if(ambulance2 > 0) { // parent
            int status;
            waitpid(ambulance1, &status, 0);
            waitpid(ambulance2, &status, 0);

            printf("HQ went home!\n");
        }
    }

    if(ambulance1 == 0 || ambulance2 == 0) {
        union sigval signalValueInt;
        signalValueInt.sival_int = SIG_INT;

        sigqueue(getppid(), SIGUSR1, signalValueInt);

        printf("Ambulance[%d] ended.\n", getpid());
    }

    return 0;
}

发生的情况是:有时第二辆救护车的 sigqueue(getppid(), SIGUSR1, signalValueInt);没有收到,输出如下:

  1. 救护车[20050] 结束。 // main() 打印出这个
  2. 救护车[20051] 结束。 // main() 打印出这个
  3. // handler() 用 write() 打印出这个 ONLY ONCE!
  4. 总部回家了! // main() 打印出这个

我知道信号丢失了,因为两个信号一个接一个来得太快了,操作系统。认为这是一个错误重复,所以它被忽略了。

我的问题是:

有没有办法告诉操作系统不要这样做?

我不想为同一目的使用两个不同的信号(例如:SIGUSR1 和 SIGUSR2),我也不想在其中一个子进程中使用延迟。

【问题讨论】:

  • sigqueue 返回什么?提示:SIGUSR1标准信号,不能排队。
  • @user58697 感谢您的回答。我在手册中查找了一些东西,发现了一些有用的信息。

标签: c signals sigaction sigqueue


【解决方案1】:

答案在 signal(7) 的手册页中。 但是简单地说: 如果在处理程序运行时标准信号到达(如 SIGUSR1),它将被操作系统忽略。 如果一个实时信号在处理程序运行时到达(如 SIGRTMIN),它将在处理程序运行完成后处理。

【讨论】:

  • 这是不准确的 — normal behavior,没有指定 SA_NODEFER,是在处理程序执行期间信号将被阻塞并保持挂起,不是它将被丢弃。跨度>
  • @pilcrow 这不是一个完整的陈述。每2.4 Signal Concepts:“如果生成了后续出现的未决信号,则在不需要排队的情况下是否多次传递或接受信号是由实现定义的。”注意挂起的确切定义“在信号生成和其交付或接受之间的时间期间,信号被称为“待处理””SA_NODEFER 仅影响交付时的信号处理。
  • 故事的寓意:编写完全取决于将传递多少非 RT 信号的代码是一个真正的坏主意
  • @AndrewHenle,是的。在我看来,这个答案似乎是在谈论“当处理程序运行时”会发生什么,这是我评论的上下文。排队在这里无关紧要:只有两个信号,第一个已经传递。如果第二个是“当 [the] 处理程序正在运行时”传递的,那么在 OP 的代码中它必然处于挂起状态。现在,上面的这个答案对于 timing 当然可能是错误的,因为两者都可能在调用处理程序之前到达挂起,在这种情况下,实现定义的队列确实发挥了作用——但这不是 OP 上面的答案考虑。
猜你喜欢
  • 1970-01-01
  • 2021-12-01
  • 2016-12-08
  • 1970-01-01
  • 2017-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多