Linux не реализует POSIX сигнальную очередь? - PullRequest
0 голосов
/ 08 ноября 2019

Статья 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;
}

]

1 Ответ

1 голос
/ 08 ноября 2019

Документированное поведение в Linux состоит в том, чтобы не ставить в очередь дублированные заблокированные сигналы.

От сигнал man 7 :

Стандартные сигналы не ставятся в очередь. Если несколько экземпляров стандартного сигнала генерируются, когда этот сигнал заблокирован, то только один экземпляр сигнала помечается как ожидающий (и сигнал будет доставлен только один раз, когда он разблокирован). В случае, когда стандартный сигнал уже находится на рассмотрении, структура siginfo_t (см. Sigaction (2)), связанная с этим сигналом, не перезаписывается при поступлении последующих экземпляров того же сигнала. Таким образом, процесс получит информацию, связанную с первым экземпляром сигнала.

Однако ... страница руководства также говорит:

Несколько экземпляров реальногосигналы времени могут быть поставлены в очередь. Напротив, если несколько экземпляров стандартного сигнала доставляются, когда этот сигнал в настоящее время заблокирован, то только один экземпляр ставится в очередь.

Вы просматриваете документацию POSIX для сигналов в реальном времени и тестируете со стандартнымте?

...