Трудно сказать, что именно не так, не видя остальную часть кода, но есть по крайней мере одна проблема с кодом вы показываете:
Перед возвращением, sigsuspend(2)
восстанавливает маску сигнала, которая была активной при ее вызове. Если вы не изменили сигнальную маску процесса соответственно до вызова sigsuspend(2)
, тогда есть время между возвратом от sigsuspend(2)
и тестированием значения flag
, где могут быть доставлены другие ожидающие сигналы (или это может быть даже в случае, если новые сигналы генерируются и доставляются). Если эти сигналы пойманы, и обработчик изменит значение flag
на другое значение, вы «потеряете» обновление, которое сделал обработчик SIGUSR2
.
Например, рассмотрим следующую программу:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
volatile sig_atomic_t flag;
void handler1(int signo) {
printf("In handler1\n");
flag = 1;
}
void handler2(int signo) {
printf("In handler2\n");
flag = 2;
}
int main(void) {
struct sigaction sigact;
sigact.sa_handler = handler1;
sigact.sa_flags = 0;
sigfillset(&sigact.sa_mask);
if (sigaction(SIGUSR1, &sigact, NULL) < 0) {
perror("sigaction()");
exit(EXIT_FAILURE);
}
sigact.sa_handler = handler2;
if (sigaction(SIGUSR2, &sigact, NULL) < 0) {
perror("sigaction()");
exit(EXIT_FAILURE);
}
sigset_t mask;
sigfillset(&mask);
sigdelset(&mask, SIGUSR1);
sigsuspend(&mask);
printf("%d\n", flag);
return 0;
}
Он ловит SIGUSR1
и SIGUSR2
, блоки каждый сигнал, кроме SIGUSR1
, а затем вызывает sigsuspend(2)
.
Запустить его, а затем отправить его SIGUSR2
, а затем SIGUSR1
. Это гарантирует, что есть ожидающий сигнал до того, как будет видно и действует SIGUSR1
. Это также приводит к SIGUSR2
быть доставлены как только SIGUSR2
разблокирован, что происходит после того, как sigsuspend(2)
возвращается (потому что мы не трогали маску сигналов процесса):
[email protected]:~/dev$ kill -SIGUSR2 29755
[email protected]:~/dev$ kill -SIGUSR1 29755
Выход:
[email protected]:~/dev$ ./a.out
In handler1
In handler2
2
Как сделать вы это исправите? Просто убедитесь, что сигнальная маска процесса установлена на ту же маску, что и в sigsuspend(2)
, так что она не ошибочно восстанавливает маску. Это так же просто, как добавление этого перед вызовом sigsuspend(2)
:
if (sigprocmask(SIG_SETMASK, &mask, NULL) < 0) {
perror("sigprocmask()");
exit(EXIT_FAILURE);
}
Итак, обновленную программу:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
volatile sig_atomic_t flag;
void handler1(int signo) {
printf("In handler1\n");
flag = 1;
}
void handler2(int signo) {
printf("In handler2\n");
flag = 2;
}
int main(void) {
struct sigaction sigact;
sigact.sa_handler = handler1;
sigact.sa_flags = 0;
sigfillset(&sigact.sa_mask);
if (sigaction(SIGUSR1, &sigact, NULL) < 0) {
perror("sigaction()");
exit(EXIT_FAILURE);
}
sigact.sa_handler = handler2;
if (sigaction(SIGUSR2, &sigact, NULL) < 0) {
perror("sigaction()");
exit(EXIT_FAILURE);
}
sigset_t mask;
sigfillset(&mask);
sigdelset(&mask, SIGUSR1);
if (sigprocmask(SIG_SETMASK, &mask, NULL) < 0) {
perror("sigprocmask()");
exit(EXIT_FAILURE);
}
sigsuspend(&mask);
printf("%d\n", flag);
return 0;
}
Это работает, как ожидалось: это гарантирует, что никакие другие обработчики сигналов не будет выполняться между окном время после sigsuspend(2)
возвращается, и вы проверяете flag
.
Еще одно важное замечание: я не знаю, как вы настроили обработчик сигналов, но если вы используете signal(2)
, тогда нет: его семантика зависит от платформы и может не вести себя так, как вы хотите. Вы должны использовать sigaction(2)
точно так, как я показываю в примере программы. Строка sigfillset(&sigact.sa_mask)
необходима, чтобы убедиться, что когда обработчик сигналов работает, все остальные сигналы по-прежнему блокируются - в противном случае доставка сигнала в середине выполнения обработчика SIGUSR1
может вызвать другой обработчик, который изменил флаг.
Пожалуйста, покажите нам [MCVE] (http://stackoverflow.com/help/mcve). – pilcrow