Мой обработчик сигналов для сигналов SIGTERM и SIGINT вызывает ошибку опроса при получении любого из них. Я не уверен, почему это происходит, и я думаю, что я не знаю о каком-то поведении, которое я пропустил.
while(!signalHandler.gotExitSignal()) {
switch (poll(&ufds[0], NUM_FDS, POLL_TIMEOUT)) {
case -1: {
throw std::runtime_error("poll error (-1)"); /* ABORT */
}
.
.
Мой signalHandler — это класс, который содержит обработку sigaction.
struct sigaction killAction, termAction;
memset(&killAction, 0, sizeof(struct sigaction));
killAction.sa_handler = SignalHandler::ExitHandler;
sigemptyset(&killAction.sa_mask);
killAction.sa_flags = 0;
if(sigaction(SIGTERM, &killAction, NULL) < 0)
throw SignalException("sigaction failed for killAction");
memset(&termAction, 0, sizeof(struct sigaction));
termAction.sa_handler = SignalHandler::ExitHandler;
sigemptyset(&termAction.sa_mask);
termAction.sa_flags = 0;
if(sigaction(SIGTERM, &termAction, NULL) < 0)
throw SignalException("sigaction failed for termAction");
Итак, мое ожидаемое поведение цикла фрагментов, которое я дал, должно быть:
Что происходит:
Я попробовал сценарий, в котором после переключения опроса я спал в течение 2 секунд, а затем завершил программу — она изящно завершилась с условием цикла. Проблема существует, пока я опрашиваю, а затем получаю сигнал. Я не использую сигнал SIGHUP, который используется для сообщения программе о необходимости перезагрузить ее конфигурацию, но я установил сигнал для проверки SIGHUP, и он завершил мою программу с ошибкой опроса, как и другие мои сигналы. Но у меня не может произойти сбой моей программы при любом сигнале, мне интересно, что я что-то забыл.
Это ожидается. При блокировке в poll () и поступлении сигнала опрос не будет выполнен, и errno будет установлен на EINTR
, Вы получите такое же поведение для большинства системных вызовов.
Вы можете и должны это обнаружить (теперь вы тоже выходите из цикла опроса, так как poll () вернется
когда сигнал пойман.)
while(!signalHandler.gotExitSignal()) {
switch (poll(&ufds[0], NUM_FDS, POLL_TIMEOUT)) {
case -1: {
if (errno == EINTR) {
continue;
}
throw std::runtime_error("poll error (-1)"); /* ABORT */
}
Скорее всего, вы хотите установить SA_RESTART
флаг для подписи тоже.
killAction.sa_flags = SA_RESTART;
Это приведет к тому, что большинство системных вызовов НЕ возвратят ошибку при обнаружении сигнала. Прочтите man-страницу для sigaction () для получения дополнительной информации и прочитайте раздел «Прерывание системных вызовов и библиотечных функций обработчиками сигналов» в человек 7 сигнал.
Примечательно, что poll () будет по-прежнему прерываться (немедленно возвращать ошибку) сигналом независимо от установки SA_RESTART
флаг.
Других решений пока нет …