Чтение сигнализируется с помощью select(), но recv() не возвращает данных и сигнализирует EAGAIN на неблокирующих сокетах
Я получил сигнальный сокет для чтения из select(), но затем по recv call() данные не поступили, вместо этого он возвращает -1 с errno==EAGAIN.
Я могу допустить, чтобы никакой другой поток не касался сокета.
Я думаю, что это поведение не является правильным. Если происходит последующее закрытие с другой стороны, я могу ожидать возвращаемого значения 0 (изящное закрытие) или другого кода ошибки из recv, но не EAGAIN, потому что, по моему мнению, это означает, что данные поступят в будущем.
Я нашел некоторую предыдущую ветку о проблеме здесь, но без решения.
Такое поведение происходит со мной в Ubuntu Linux Oneric или других последних дистрибутивах Linux, затем информация по ссылке размещена здесь
То, что это будет исправлено в ядре, неверно для ядра 3.0.0 или последней версии 2.6.x
У кого-нибудь есть идея, почему это происходит и как избежать этого нежелательного поведения?
2 ответа
Select(), сообщающий сокет как читаемый, не означает, что есть что прочитать; это означает, что чтение не будет блокироваться. Чтение может вернуть -1 или 0, но не заблокирует.
ОБНОВИТЬ:
После того, как select возвращает readable: если read() возвращает -1, проверьте errno. EAGAIN/EWOULDBLOCK и EINTR - это значения, которые должны обрабатываться особым образом: в основном, путем повторного вызова read(), но вы можете доверять циклу выбора, возвращающему readable в следующий раз.
Если задействовано несколько потоков, все может стать сложнее.
У меня та же проблема, но с epoll. Я заметил, что это происходит всякий раз, когда система повторно использует номера FD сокетов, которые уже закрыты. После некоторых исследований я заметил, что такое поведение вызвано закрытием сокетов, когда они надеваются на них. Старайтесь избегать запуска select на сокете при его закрытии - это может помочь.