4

在 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成员与给出的osa匹配。masksigprocmask

POSIX 是否为此字段指定任何要求?手册中唯一提到它的是关于不可阻塞的信号,例如SIGKILL,其中未指定该值。

在 linux 上,这个程序打印:

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 版本是:

$ 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

二进制文件链接到:

/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
4

1 回答 1

8

我希望 的sa_mask成员与给出的osa匹配。masksigprocmask

你的期望是不正确的。

这是当前(撰写本文时)官方 POSIX 文档的链接。收藏它!

这是该文档所说的内容sa_mask

在执行信号捕获功能期间要阻塞的附加信号集。

没有理由期望osa.sa_mask匹配mask。你mask的是当前的信号掩码。你osa.sa_mask是一个额外的信号掩码,在调用osa.sa_handler处理一个SIGALRM.

在您的测试用例中,osa.sa_handleris SIG_DFL,因此 的内容osa.sa_mask无关紧要。据我所知(经过简短的搜索),POSIX 没有说明什么osa.sa_mask时候应该是什么时候,就像在你的测试用例中一样,自最近的exec.

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

当一个信号被 安装的信号捕获函数捕获时sigaction(),一个新的信号掩码被计算并在信号捕获函数的持续时间内安装(或直到调用其中一个sigprocmask()sigsuspend())。该掩码是通过将当前信号掩码与sa_mask正在传递的信号的值结合而形成的,除非设置了SA_NODEFER或,否则SA_RESETHAND将包括正在传递的信号。

因此,sa_maskincludes SIGALRMif 是否sa_flags为 0 无关紧要。Linux 不包括它而 OS X 确实对信号的处理没有影响。

还要注意,(对我而言)不清楚为 的参数传递 0(而不是定义的常量之一)是合法howsigprocmask,即使set参数为空也是如此。但我发现将其更改为SIG_BLOCK没有任何区别。

于 2014-12-02T21:40:27.250 回答