Принять вызов, которому мешает обработчик сигнала

Я использую вызов accept для сокета, который должен принимать соединения только с клиентскими процессами. Однако обработчик сигнала, реализованный с sigaction для сигнала SIGALRM, регистрируется как жизнеспособное соединение. Я думаю, что я должен проверить соединение с выбором или опросом, но я не уверен, что это только усложняет это. Любая помощь будет оценена.

Изменить: Извините, что сказал, что это была связь. Похоже, это была связь. В моем коде был цикл while с условием, которое выполнялось до тех пор, пока accept не оценивалось до 0.

Обновление: так что я только что нашел свою проблему. Флаг sigaction был по умолчанию. Я изменил его на SA_RESTART и теперь он работает нормально. Я думаю, что это как-то связано с игнорированием примитивного ввода-вывода и возвращением EINTR, но я не совсем уверен в этом. Кто-нибудь знает?

1 ответ

В Linux системные вызовы (включая accept) могут быть прерваны сигналами.

Если сигнал получен во время выполнения системного вызова, системный вызов будет прерван и вернет ошибку EINTR, Несмотря на то, что это "ошибка", это не значит, что что-то пошло не так, просто нужно повторить вызов. Обоснование этого дизайна довольно сложно и выходит за рамки этого вопроса.

Как вы узнали, вы можете установить sigaction флаг SA_RESTART чтобы этого не произошло для конкретного сигнала. accept возвращает -1, если обнаружит ошибку, поэтому это будет выглядеть примерно так:

while(1)
{
    int client_sock = accept(...);
    if(client_sock == -1)
    {
        if(errno == EINTR)
            continue; // try again
        ... normal error handling here ...
    }
    else
    {
        ... normal connection handling here ...
    }
}

Более надежным решением было бы специально проверить EINTR - в случае, если ваша программа получает сигнал, к которому она не была подготовлена, или в случае, если какой-то другой код использует сигналы и не устанавливает SA_RESTART. (Это может быть ваш код, который вы пишете через 3 месяца)

Другие вопросы по тегам