Добрый день,
Я столкнулся со следующей проблемой. Есть TCP-сервер построенный на технологии портов завершения ввода-вывода. Есть 20 клиентов, которые в целях тестирования непрерывно выполняют следующие команды: Connect, Send (3байта), Disconnect. Клиенты запущены на той же машине, что и сервер.
Основная функция рабочего потока сервера выглядит стандартно для IOCP, примерно так:
Есть класс CIOReq наследованный от OVERLAPPED, который несет дополнительную информацию об операциях.
Функция HandleOperation имеет некоторую логику и делает следующие вызовы:
1.
...
pIOReq = new CIOReq();
...
int nRes = WSASend(socket, pWSABUF , 1, &dwLen, dwFlags, (OVERLAPPED*)pIOReq, NULL);
Иногда (при указанной нагрузке 20 клиентов, в среднем раз в 30 секунд, иногда чаще, иногда реже), WSASend и WSARecv вываливаются с исключением 0x00000005 Access violation.
При этом поля класса pIOReq оказываются невалидными, как будто объект удален. Данное исключение выскакивает в отладчике и не перехватывается ни try-catch ни __try — __except
Экспериментально выяснилось, если количество рабочих потоков сделать равным 1 (обычно запущено 10), такой ошибки не возникает.
Если сделать защиту (собственный механизм) указателя pIOReq от удаления, до возврата из WSASend, WSARecv, то ошибки тоже не возникает, а отлавливается попытка удалить объект до снятия защиты.
Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv.
Он удаляет объект pIOReq и в WSASend/WSARecv происходит нарушение доступа.
Вопросы:
как сигнал о завершении ввода-вывода может поступать до завершения асинхронной функции ввода-вывода,
почему это исключение не отлавливается стандартными средствами обработки исключений
что с этим делать?