Принять вызов, которому мешает обработчик сигнала
Я использую вызов 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 месяца)