OS X sigaction incorrectly sets sa_mask

On macbook (OSX 10.9.5 (13F34)) the following is a simple program:

#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;
}

      

Mysteriously prints:

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

      

I would expect the member sa_mask

osa

to match mask

as given sigprocmask

.

Does POSIX specify any requirements for this field? The only mention of this in the manpages is for non-blocking signals, such as SIGKILL

where this value is not specified.

On linux, this program prints:

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

      

as was expected.

Gcc version:

$ 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

      

The binary is associated with:

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

      

+3


source to share


1 answer


I would expect the member sa_mask

osa

to match mask

as given sigprocmask

.

Your expectation is wrong.

Here's a link to the current (at the moment) official POSIX documentation . Bookmark!

Here's what the documentation says sa_mask

:

An additional set of signals to be blocked during the signal capture function.

There is no reason to expect it osa.sa_mask

to match mask

. Yours mask

is the signal mask current . Yours osa.sa_mask

is an additional signaling mask that would be applied during the call osa.sa_handler

for processing SIGALRM

.



In your test case osa.sa_handler

there is SIG_DFL

, so the content osa.sa_mask

doesn't matter. As far as I know (after a short search), POSIX says nothing about what should be osa.sa_mask

when, as in your test case, the process has not set an action for the signal since the very last exec

.

In addition, when the system calls the installed handler SIGALRM

, it automatically includes the SIGALRM

signal mask (if you have not passed SA_NODEFER

or SA_RESETHAND

when installing the handler). To quote the above documentation:

When a signal is captured by the signal capture function set sigaction()

, a new signal mask is calculated and set for the duration of the signal capture function (or before calling either sigprocmask()

or sigsuspend()

). This mask is formed by combining the mask of the current signal and the value sa_mask

for the transmitted signal, and if not set to SA_NODEFER

or SA_RESETHAND

, then including the transmitted signal.

So it doesn't matter if it includes sa_mask

SIGALRM

, if sa_flags

is 0. The fact that Linux doesn't include it and OS X has nothing to do with signal processing.

Note also that it is not clear (to me) that it is legal to pass 0 (instead of one of the defined constants) for an argument how

sigprocmask

, even if the argument set

is zero. But I found that changing it to SIG_BLOCK

didn't matter.

+7


source







All Articles