Информация об изменениях

Сообщение Re: UB в сетевом API Windows от 02.04.2025 20:49

Изменено 02.04.2025 20:50 Videoman

Re: UB в сетевом API Windows
Здравствуйте, Videoman, Вы писали:

V>Создаю UDP сокет под WSA как обычно:
V>handle = ::socket(AF_INET, SOCK_DGRAM, 0);
V>

V>Связываю сокет с адресатом через ::connect() (соединение естественно реально не устанавливается)

V>Задаю таймаут на прием:

V>
V>const int timeout = 500;
V>::setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<const char*>(&timeout), sizeof(timeout)));
V>

V>Принимаю в цикле данные с помощью WSARecv() в блокирующем режиме (без OVERLAPPED).

V>В случае, если пакеты приходят, всё нормально. Если пакетов нет, то ожидаемо возвращается SOCKET_ERROR и WSAGetLastError() возвращает WSAETIMEDOUT. Так работает почти везде.

V>Но на одном очень быстром сервере (128 ядер), иногда, вместо WSAETIMEDOUT возвращается WSA_IO_PENDING. Т.е. на блокирующем вызове (только по истечении таймаута) функция WSARecv возвращает, что операция не завершена и активна (потенциально). Тут я уже напрягся, т.к. OVERLAPPED создается внутри на стеке и потенциально драйвер может туда записать.
V>После продолжительных тестов на этом сервере опасения подтвердились: код падал в случайных местах незадолго после возврата из WSARecv.

V>Вопрос к знатокам, как такое поведение вообще возможно? Это баг реализации ? Если да, то на каком уровне проблема может быть?


V>P.S. Всё это было нужно только для того, что бы использовать таймаут на приеме пакетов по UPD и обошел я это реализацией своей блокирующей версией, которая явно использует OVERLAPPED и вызывает у него CancelIOEx() и дожидается c помощью WSAGetOverlappedResult() реального завершения операции. Вроде пока пронесло, но осадочек отрицательный остался.
Re: UB в сетевом API Windows