Статья POSIX для sigaction
гласит:
Если SA_SIGINFO установлен в sa_flags, то последующие вхождения sig генерируются sigqueue () или в результате любогогенерирующая сигнал функция, которая поддерживает спецификацию определяемого приложением значения (когда sig уже ожидает) должна быть поставлена в очередь в порядке FIFO, пока не будет доставлена или принята;функция перехвата сигнала должна вызываться с тремя аргументами. Указанное приложением значение передается в функцию перехвата сигнала как член si_value структуры siginfo_t.
Это ничего не говорит о слиянии вхождений одного и того же сигнала (signo
). И даже если бы это означало слияние, фраза о FIFO была бы неполной. Например, если FIFO равен [SIGALRM, SIGIO, SIGUSR1, SIGIO]
, что будет после слияния, [SIGALRM, SIGIO, SIGUSR1]
или [SIGALRM, SIGUSR1, SIGIO]
?
Однако я видел несколько отчетов ( 0 , 1 , 2 ), что Linux действительно объединяет вхождения одного и того же сигнала. Я также написал небольшую тестовую программу, которая подтверждает, что экземпляры одного и того же сигнала, отправленного с sigqueue
, когда этот сигнал заблокирован, объединены в ArchLinux. Обработчик сигнала был установлен с sigaction
.
Linux [skipped] 5.3.8-arch1-1 #1 SMP PREEMPT [skipped] x86_64 GNU/Linux
Если вхождения одного и того же сигнала объединяются, то передача информации через union sigval
не имеет смысла, поскольку эта информация может быть непредсказуемо потеряна.
Мое понимание POSIX неверно или Linux неправильно его реализует?
[Обновление 2019-11-09 09: 51: 32 + 00: 00. Я нашел другой кусок документации, которая подтверждает мою точку зрения. Согласно статья «2. Общая информация »,
Если генерируется последующее вхождение ожидающего сигнала, это определяется реализацией относительно того, был ли сигнал доставлен или принят более одного раза в обстоятельствах прочеечем те, в которых требуется организация очереди .
и еще один на sigqueue
,
Если SA_SIGINFO установлен для signo иесли ресурсы были доступны для постановки в очередь сигнала, сигнал должен быть помещен в очередь и отправлен в процесс приема.
Функция sigqueue () завершится ошибкой, если:
[EAGAIN] Нет доступных ресурсов для постановки в очередь сигнала. Процесс уже поставил в очередь сигналы {SIGQUEUE_MAX}, которые все еще ожидают на приемнике (получателях), или превышен лимит общесистемного ресурса.
Я использовал sigaction
с установленным SA_SIGINFO
и sigqueue
. Функция sigqueue
не вернула EAGAIN
.]
[Обновление 2019-11-09 17: 45: 25 + 00: 00. Моя тестовая программа. Функции sigprint
предназначены для печати с использованием write
и статически выделенного буфера;они не важны.
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include "sigprint.h"
void signal_handler(int signo, siginfo_t *info, void *context) {
sigprint_string("|");
sigprint_long(info->si_value.sival_int);
sigprint_flush();
}
void sigqueue_check(pid_t pid, int signo, union sigval value) {
if (sigqueue(pid, signo, value) == -1) {
printf(" returned error code %d which is %s to EAGAIN.\n",
errno, errno == EAGAIN ? "==" : "!=");
exit(24);
}
}
int main() {
struct sigaction sigaction0;
union sigval sigval0;
sigset_t sigset0, sigset1;
sigaction0.sa_sigaction = &signal_handler;
sigemptyset(&sigaction0.sa_mask);
sigaction0.sa_flags = SA_SIGINFO | SA_RESTART;
sigaction(SIGALRM, &sigaction0, NULL);
sigemptyset(&sigset0);
sigaddset(&sigset0, SIGALRM);
sigprocmask(SIG_BLOCK, &sigset0, &sigset1);
sigval0.sival_int = 10;
sigqueue_check(getpid(), SIGALRM, sigval0);
sigval0.sival_int = 11;
sigqueue_check(getpid(), SIGALRM, sigval0);
sigval0.sival_int = 12;
sigqueue_check(getpid(), SIGALRM, sigval0);
sigprocmask(SIG_SETMASK, &sigset1, NULL);
sleep(1);
return 0;
}
]