C sigwaitinfo()可以等待进程信号掩码的超集吗?

C sigwaitinfo()可以等待进程信号掩码的超集吗?,c,signals,posix,C,Signals,Posix,例如,我试图正确地进行模拟,但当set参数选择的多个信号同时发送到等待其中一个函数的进程时,我无法掌握预期的行为 例如,第一个信号将导致sigwaitinfo返回,填充info参数。 但是第二个信号呢?就我所见,如果第二个信号没有被阻塞(它不包括在进程信号掩码中),进程应该接收它,中断第一个信号管理,降低使用这些功能组的优势 这让我想知道,提供给这些函数的集合是否总是过程信号掩码的一个子集,或者是否有我遗漏的其他东西 换句话说:Linux手册页面声明 在正常使用中,调用程序通过对sigprocm

例如,我试图正确地进行模拟,但当
set
参数选择的多个信号同时发送到等待其中一个函数的进程时,我无法掌握预期的行为

例如,第一个信号将导致sigwaitinfo返回,填充
info
参数。 但是第二个信号呢?就我所见,如果第二个信号没有被阻塞(它不包括在进程信号掩码中),进程应该接收它,中断第一个信号管理,降低使用这些功能组的优势

这让我想知道,提供给这些函数的
集合
是否总是过程信号掩码的一个子集,或者是否有我遗漏的其他东西

换句话说:Linux手册页面声明

正常使用中,调用程序通过对sigprocmask(2)的先前调用阻止集合中的信号(因此,如果这些信号在对sigwaitinfo()或sigtimedwait()的连续调用之间处于挂起状态,则不会发生这些信号的默认处理),并且不会为这些信号建立处理程序


我想知道这个“正常用法”是这个API唯一正确的用法,或者在一些适当的用例中,
set
参数包含的信号比进程信号掩码多。

这段小代码试图回答您的评论,在Ubuntu上似乎可以正常工作

// ctrl-c handler
void cc(int s) {
    static int count = 0;
    printf("Entering cc %d\n", ++count);
    sleep (5);
    printf("Leaving cc %d\n", count);
}

int main(int argc, char **argv) {
    signal(SIGINT, cc); // ctrl-c

    int n = 10; // leave after 10 ctrl-c
    while (n--) {
        pause();
    }
    return 0;
}
Ctrl-C被捕获并执行
cc
cc
递增并打印一个数字,我们希望在离开函数时显示相同的数字。如果
cc
在其执行完成(睡眠5)之前由于另一个Ctrl-C而被重新输入,我们将得到如下结果

Entered cc 1
Entered cc 2
Leaving cc 2
Leaving cc 2
不建议在信号处理程序中执行一些I/O操作,如
printf
,但在我们的小例子中,没有共享冲突,即使我们有一些标准输出缓冲,如果重新输入
cc
,则“离开文本”最终将与上面类似

但那没有发生。在
cc
处于睡眠状态时按另一个Ctrl-C键,第二个事件似乎在某个地方挂起(似乎只保留了一个事件)<代码>睡眠()可能有特殊行为?无论如何,在这种情况下,
cc
将在睡眠后重新输入,并显示上面不想要的行为

另一个值得注意的行为是main中的
pause()
。如果在另一个Ctrl-C处于“睡眠”状态时按下另一个Ctrl-C,则第二个Ctrl-C将在相同的“暂停”时间内执行(类似于
while(event){process(event);}
;此行为由离开程序必须执行的Ctrl-C次数显示:应为10,但实际上是在处理前一个按键时按下该键的10+次数


不过,我不确定这是否适用于您的系统以及任何事件。

我想这取决于您所说的“正确”是什么意思

正常使用是唯一合理的使用

异常使用是允许的,因为它不会引起未定义的行为。它也是毫无意义的,危险的复杂。您的实现将有一些算法,用于为一个进程分派两个挂起的信号,该进程是
sigwait
ing两者,SIG_都不忽略,最多阻塞一个。*该进程是否能够然而,它的设计是正确的


*根据POSIX-1.2008的信号概念,假设非实时信号。

根据经验,我会说,如果一个处理程序在另一个相同事件发生时没有完成,那么第二个处理程序将排队,并将在第一个处理程序完成后启动。@RingØ:恐怕POSIX信号不计入“事件队列”。至少如果sigprocmask()不用于阻止它们。但是,如果您可以通过我可以在Linux和NetBSD上运行的小型C测试来显示此行为,我会将其视为有效答案。虽然您的帖子实际上没有回答这个问题(关于sigwait、sigwaitinfo和sigtimedwait),我必须感谢你,因为你质疑我对标准的理解,并证明它可能是错误的。GNU Libc实际上在信号处理程序调用期间阻止了信号:我在POSIX文档中找不到这种行为的参考。正确的说法是符合POSIX。@RingØ显示了一个有趣的例子(对我来说完全出乎意料)在Linux上发生的行为。但是它与
signal
,而不是
sigwait
和friends有关。@GiacomoTesio,
signal
(在Linux上)在处理程序执行期间阻止触发处理程序的信号(由于缺乏灵活性和历史变幻莫测,因此不应使用它-请改用
sigaction
)。此外,普通UNIX信号不排队,因此一次只能有一个挂起。我认为这解释了@RingØ的行为。关于@RingØ行为的要点是它是Linux特定的行为还是POSIX指定的行为。此外,好吧,普通UNIX信号不排队,因此每个数字中在任何时候都只能有一个挂起。然而据我所知,文件中可能有多个不同编号的挂起非实时信号(它们的交货订单将未指定)。这是否错误?是的,您可以同时挂起USR1、HUP和TERM。您想另外提问吗?