Чтение сигнализируется с помощью 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 на сокете при его закрытии - это может помочь.

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