Сигнал HUP при чтении процесса из cin - PullRequest
2 голосов
/ 05 мая 2020

У меня есть исполняемый файл, который всегда читает ввод из std :: cin в al oop, у меня также есть обработчик SIGHUP.

#include <iostream>
#include <signal.h>

void hupHandler(int)
{
    std::cout << "Handled sighup" << std::endl;
}

int main(int, char*[])
{
    struct sigaction sigHupHandler{};
    sigHupHandler.sa_handler = hupHandler;
    sigemptyset(&sigHupHandler.sa_mask);
    sigHupHandler.sa_flags = 0;
    sigaction(SIGHUP, &sigHupHandler, nullptr);

    while(true)
    {
        std::string input;
        std::getline(std::cin, input);
        std::cout << "Read input \"" << input << "\"" << std::endl;
    }

    std::cout << "Child Exiting" << std::endl;

    return 0;
}

Когда я запускаю исполняемый файл на своем терминале и отправляю SIGHUP с помощью kill -HUP, я вижу, что он обрабатывает SIGHUP, но после этого я вижу бесконечную печать следующего:

$ ./child 
Handled sighup
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""

Кто-нибудь, пожалуйста, объясните мне это поведение? На самом деле мне нужен процесс, который работает в фоновом режиме и постоянно прослушивает его стандартный ввод (другой процесс передает его на стандартный ввод). Мне также нужно перезагрузить конфигурацию, если она была SIGHUP. Я заметил, что как только я HUP, он перешел на oop чтения пустых строк. Я написал эту утилиту для тестирования и вижу то же поведение. Любая помощь будет оценена, спасибо!

1 Ответ

2 голосов
/ 05 мая 2020

Вы не можете просто делать в обработчике сигналов все, что хотите. Обработчик сигнала может прервать выполнение программы в любое время . В том числе, когда он выполняет что-то внутри функции библиотеки C ++ или класса, и ни одна из функций библиотеки C ++, шаблонов и т. Д. Не является реентерабельной, как это. Вы, в значительной степени, не можете использовать какой-либо код библиотеки C ++, и уж тем более std::cout, в обработчике сигналов. Вы даже не можете сделать new или delete ничего. Это первая проблема.

Вы также не можете использовать C библиотечные функции. Они тоже не реентерабельны. Единственное, что вы можете сделать в обработчике сигналов, - это использовать вызовы операционной системы, такие как open / close / read / write и т. Д. (в основном, раздел 2 страниц руководства), напрямую.

Из-за этого показанный код является неопределенным поведением, и вы не можете ожидать, что он будет работать надежно, в любом виде, форме, материи или форме, поскольку пока ваш обработчик сигналов делает то, что делает.

Более того, когда процесс находится в середине самого системного вызова (в зависимости от указанного c системного вызова), перехваченный сигнал приводит к сбою с спецификацией c errno из EINTR. Это описано на вашей signal(7) странице руководства, которую вы должны прочитать. Библиотека C ++, скорее всего, интерпретирует это как любую другую ошибку при чтении из файла и переведет поток в состояние сбоя, что похоже на поведение, которое вы наблюдаете. Вы тоже должны справиться с этим самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...