Чтение сигнализируется с помощью select (), но recv () не возвращает данных и сигнализирует EAGAIN на неблокирующих сокетах - PullRequest
5 голосов
/ 24 ноября 2011

У меня есть сигнальный сокет для чтения из select (), но затем никакие данные не были получены вызовом recv (), вместо этого он возвращает -1 с errno == EAGAIN.

Я могу допустить, чтобы никакой другой поток не касался сокета.

Я думаю, что это поведение не правильно. Если происходит последующее закрытие с другой стороны, я могу ожидать возврата значения 0 (изящное закрытие) или другого кода ошибки из recv, но не EAGAIN, потому что, по моему мнению, это означает, что данные поступят в будущем.

Я нашел предыдущую ветку о проблеме здесь , но без решения.

Такое поведение происходит со мной в Ubuntu Linux Oneric или других последних дистрибутивах Linux, затем информация по ссылке, размещенной здесь

То, что это будет исправлено в ядре, неверно для ядра 3.0.0 или более поздней версии 2.6.x

Кто-нибудь знает, почему это происходит и как избежать этого нежелательного поведения?

Ответы [ 2 ]

5 голосов
/ 24 ноября 2011

Select (), сообщающий сокет как читаемый, не означает, что есть что-то для чтения; это означает, что чтение не будет блокироваться. Чтение может вернуть -1 или 0, , но не заблокирует .

UPDATE:

После того, как select возвращает readable: если read () возвращает -1, проверьте errno. EAGAIN / EWOULDBLOCK и EINTR - это значения, которые должны обрабатываться особым образом: в основном, путем повторного вызова read (), но вы можете доверять циклу выбора, возвращающему читаемый в следующий раз.

Если задействовано несколько потоков, все может стать сложнее.

0 голосов
/ 01 сентября 2013

У меня та же проблема, но с epoll. Я заметил, что это происходит всякий раз, когда система повторно использует номера FD сокетов, которые уже закрыты. После некоторых исследований я заметил, что такое поведение вызвано закрытием сокетов во время их эполинга. Старайтесь избегать запуска select на сокете при его закрытии - это может помочь.

...