On a macbook (OSX 10.9.5 (13F34)) the following 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 that the sa_mask
member of osa
to match mask
as given by sigprocmask
.
Does POSIX specify any requirements for this field? The only mention of it in the manpages is with regard to unblockable signals like SIGKILL
, where that value is unspecified.
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 expected.
The gcc version is:
$ 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 linked against:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
I would expect that the
sa_mask
member ofosa
to matchmask
as given bysigprocmask
.
Your expectation is incorrect.
Here's a link to the current (as of this writing) official POSIX documentation. Bookmark it!
Here is what that documentation says about sa_mask
:
Additional set of signals to be blocked during execution of signal-catching function.
There is no reason to expect osa.sa_mask
to match mask
. Your mask
is the current signal mask. Your osa.sa_mask
is an additional signal mask that would have been applied during a call to osa.sa_handler
to handle a SIGALRM
.
In your test case, osa.sa_handler
is SIG_DFL
, so the contents of osa.sa_mask
is irrelevant. As far as I know (after a brief search), POSIX says nothing about what osa.sa_mask
should be when, as in your test case, the process hasn't set an action for the signal since the most recent exec
.
Furthermore, when the system calls an installed SIGALRM
handler, it includes SIGALRM
in the signal mask automatically (unless you passed SA_NODEFER
or SA_RESETHAND
when you installed the handler). Quoting the documentation linked above:
When a signal is caught by a signal-catching function installed by
sigaction()
, a new signal mask is calculated and installed for the duration of the signal-catching function (or until a call to eithersigprocmask()
orsigsuspend()
is made). This mask is formed by taking the union of the current signal mask and the value of thesa_mask
for the signal being delivered, and unlessSA_NODEFER
orSA_RESETHAND
is set, then including the signal being delivered.
Thus it's irrelevant whether sa_mask
includes SIGALRM
if sa_flags
is 0. The fact that Linux doesn't include it and OS X does makes no difference to the handling of the signal.
Note too that it's not clear (to me) that it's legal to pass 0 (instead of one of the defined constants) for the how
argument of sigprocmask
, even when the set
argument is null. But I found that changing it to SIG_BLOCK
made no difference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With