OS X sigaction错误地设置了sa_mask

时间:2014-11-26 21:33:06

标签: c macos language-lawyer sigprocmask sigaction

在macbook(OSX 10.9.5(13F34))上有以下简单程序:

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

static void nop(int unused) { }

int
main(void) {
    struct sigaction sa, osa;
    sigset_t mask;

    sigemptyset(&sa.sa_mask);
    printf("Errno after sigempty sa_mask: %d\n", errno);
    sigemptyset(&osa.sa_mask);
    printf("Errno after sigempty oldsa_mask: %d\n", errno);
    sa.sa_flags = 0;
    sa.sa_handler = nop;

    sigprocmask(0, NULL, &mask);
    printf("Errno after sigprocmask mask: %d\n", errno);
    printf("%d\n", sigismember(&mask, SIGALRM));

    sigaction(SIGALRM, &sa, &osa);
    printf("Errno after sigaction sa osa: %d\n", errno);
    printf("%d\n", sigismember(&osa.sa_mask, SIGALRM));
    printf("%d\n", sigismember(&sa.sa_mask, SIGALRM));

    return 0;
}

神秘印刷:

Errno after sigempty sa_mask: 0
Errno after sigempty oldsa_mask: 0
Errno after sigprocmask mask: 0
0
Errno after sigaction sa osa: 0
1
0

我希望sa_mask的{​​{1}}成员与osa的{​​{1}}匹配mask

POSIX是否指定了此字段的任何要求?在联机帮助页中唯一提到的是关于像sigprocmask这样的不可阻塞的信号,其中该值未指定。

在linux上,该程序打印:

SIGKILL

正如所料。

gcc版本是:

Errno after sigempty sa_mask: 0
Errno after sigempty oldsa_mask: 0
Errno after sigprocmask mask: 0
0
Errno after sigaction sa osa: 0
0
0

二进制文件与以下内容相关联:

$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
Target: x86_64-apple-darw

1 个答案:

答案 0 :(得分:7)

  

我希望sa_mask的{​​{1}}成员与osa给出的mask匹配。

您的期望不正确。

这是the current (as of this writing) official POSIX documentation的链接。收藏它!

Here is what that documentation says about sa_mask:

  

执行信号捕捉功能时要阻止的附加信号集。

没有理由期望sigprocmaskosa.sa_mask匹配。您的mask当前信号掩码。您的mask是一个附加信号掩码,在调用osa.sa_mask以处理osa.sa_handler时已应用。

在您的测试用例中,SIGALRMosa.sa_handler,因此SIG_DFL的内容无关紧要。据我所知(在简短的搜索之后),POSIX没有说明osa.sa_mask应该是什么时候,就像你的测试案例一样,这个过程自最近以来没有为信号设置一个动作{ {1}}。

此外,当系统调用已安装的osa.sa_mask处理程序时,它会自动在信号掩码中包含exec(除非您在安装处理程序时通过SIGALRMSIGALRM )。引用上面链接的文档:

  

当信号被SA_NODEFER安装的信号捕获功能捕获时,会在信号捕获功能的持续时间内计算并安装新的信号掩码(或直到调用SA_RESETHANDsigaction()。该掩模是通过将当前信号掩码与正在传递的信号的sigprocmask()的值结合而形成的,除非设置sigsuspend()sa_mask,否则包括信号递送

因此,如果SA_NODEFER为0,SA_RESETHAND是否包含sa_mask则无关紧要.Linux不包含它和OS X的事实对我来说无关紧要处理信号。

另请注意,对于SIGALRM的{​​{1}}参数,传递0(而不是一个已定义的常量)是合法的(对我来说)是不合法的,即使sa_flags参数为null。但我发现将其更改为how没有任何区别。