OS X sigaction неправильно устанавливает sa_mask
На 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
соответствовать mask
как указано sigprocmask
,
POSIX определяет какие-либо требования для этого поля? Единственное упоминание об этом в man-страницах в отношении таких неблокируемых сигналов, как 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)
1 ответ
Я ожидаю, что
sa_mask
членosa
соответствоватьmask
как указаноsigprocmask
,
Ваше ожидание неверно.
Вот ссылка на текущую (на момент написания) официальную документацию POSIX. Закладка это!
Вот что говорится в этой документации sa_mask
:
Дополнительный набор сигналов, блокируемых во время выполнения функции захвата сигналов.
Нет причин ожидать osa.sa_mask
соответствовать mask
, Ваш mask
текущая маска сигнала. Ваш osa.sa_mask
дополнительная маска сигнала, которая была бы применена во время вызова osa.sa_handler
обращаться с SIGALRM
,
В вашем тестовом случае osa.sa_handler
является SIG_DFL
, так что содержание osa.sa_mask
не имеет значения. Насколько я знаю (после непродолжительного поиска), POSIX ничего не говорит о том, что osa.sa_mask
должно быть, когда, как в вашем тестовом примере, процесс не установил действие для сигнала с самого последнего exec
,
Кроме того, когда система вызывает установленный SIGALRM
обработчик, включает в себя SIGALRM
в маске сигнала автоматически (если вы не прошли SA_NODEFER
или же SA_RESETHAND
когда вы установили обработчик). Цитирование документации, связанной выше:
Когда сигнал улавливается функцией захвата сигнала, установленной
sigaction()
новая маска сигнала вычисляется и устанавливается на время действия функции перехвата сигнала (или до вызоваsigprocmask()
или жеsigsuspend()
сделан). Эта маска формируется путем объединения маски текущего сигнала и значенияsa_mask
для доставляемого сигнала, и еслиSA_NODEFER
или жеSA_RESETHAND
устанавливается, затем включая сигнал, который доставляется.
Таким образом, не имеет значения, sa_mask
включает в себя SIGALRM
если sa_flags
равно 0. Тот факт, что Linux не включает его, а OS X не имеет никакого значения для обработки сигнала.
Заметьте также, что не ясно (для меня), что допустимо передавать 0 (вместо одной из определенных констант) для how
аргумент sigprocmask
даже когда set
аргумент нулевой. Но я обнаружил, что меняя его на SIG_BLOCK
не имеет значения.