Здравствуйте, Armastab, Вы писали:
A>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv.
Такая ситуация вполне реальна и происходит достаточно часто, особенно на многопроцессорных системах. Я обычно делаю счетчик ссылок, инкрементирую его перед вызовом WSASend/WSARecv, а декрементирую в обработчике IOCP или в случае ошибки WSASend/WSARecv (не-IO_PENDING, т.е. когда обработчик вызываться не будет).
Re: Исключение Access violation в WSASend и WSARecv (IOCP)
Здравствуйте, Armastab, Вы писали:
A>Иногда (при указанной нагрузке 20 клиентов, в среднем раз в 30 секунд, иногда чаще, иногда реже), WSASend и WSARecv вываливаются с исключением 0x00000005 Access violation. A>При этом поля класса pIOReq оказываются невалидными, как будто объект удален. Данное исключение выскакивает в отладчике и не перехватывается ни try-catch ни __try — __except
Вероятно в этот момент удалена структура CIOReq или сами буфера чтения/записи. Поскольку сама асинхронная операция в этот момент выполняется не в рабочем потоке процесса система выплевывает исключение которое не будет поймано. Или будет поймано "без стека", или вы увидите на экране "Приложение выполнило недопустимую операцию и будет закрыто", если отладки не было.
A>Экспериментально выяснилось, если количество рабочих потоков сделать равным 1 (обычно запущено 10), такой ошибки не возникает. A>Если сделать защиту (собственный механизм) указателя pIOReq от удаления, до возврата из WSASend, WSARecv, то ошибки тоже не возникает, а отлавливается попытка удалить объект до снятия защиты.
Это потому что в одном потоке все вызовы будут сериализированы.
A>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv. A>Он удаляет объект pIOReq и в WSASend/WSARecv происходит нарушение доступа.
Тут сложно сказать наверняка, не видя кода, но это предположение скорее всего ошибочное.
A>Вопросы: A>как сигнал о завершении ввода-вывода может поступать до завершения асинхронной функции ввода-вывода, A>почему это исключение не отлавливается стандартными средствами обработки исключений A>что с этим делать?
Отлаживать Стоит подумать о счетчике ссылок в CIOReq (раз уж есть механизм защиты от его удаления)
Re[6]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Armastab, Вы писали:
A>Странность в том, что срабатывание обработчика, по моему мнению, происходит до того, как WSARecv/WSASend закончили свою работу и вернули управление в вызывающий их поток. Т.к. WSARecv/Send еще не отработал до конца, а OVERLAPPED уже рарзушено в другом процессе внезапно сработавшим обработчиком, возникает исключение.
Ерунда. Обработчик вызывается только после завершения WSARecv/WSASend, иначе быть не может. Может тебе так кажется на двух ядрах?
В обработчике можешь смело удалять структуру. Если вылазит ошибка — ищи баг.
Re[3]: Исключение Access violation в WSASend и WSARecv (IOCP
вот поднял исходники, у меня исключительно под отладчиком происходило псевдосрабатывание GetQueuedCompletionStatus() и именно когда рабочих потоков более одного,
при этом @err = 87 (ERROR_INVALID_PARAMETER)
фенька была именно под отладчиком, но вот бодался пока не сообразил
Re[11]: Исключение Access violation в WSASend и WSARecv (IOC
Здравствуйте, Pepel, Вы писали:
P>я так понял : асинхронная операция, инициируемая вызовом WSARecv/WSASend, может завершиться РАНЬШЕ, чем сама функция WSARecv/WSASend вернет управление
Да.
P>и по этой причине обработчик завершения может грохнуться , ну понятно почему
Грохнуться может неправильно реализованный обработчик.
P>это реально правда ?
Да, вполне. Это ошибка — предполагать, что обработчик будет вызван позже, чем следующая за WSARecv/WSASend инструкция.
P>но тогда какие счетчики ? нужна синхронизация полноценная , евенты теж — выставляем евент по возврату из WSARecv/WSASend , а на обработчике завершения ждем пока евент в UP не станет
TMTOWTDI. Я лишь привел один из возможных способов, который годится для описанной Armastab ситуации. Ему ведь главное — не удалить объект CIOReq преждевременно.
P>и вообщем странно, что такие .. не ну гвозди .. и нигде не описаны
Они следуют из общей архитектуры системы, причем любой современной системы. Возврат из системного вызова происходит не мнгновенно, и за это время в другом потоке может много чего произойти.
Re[14]: Исключение Access violation в WSASend и WSARecv (IOC
Здравствуйте, Pepel, Вы писали:
P>Michael Chelnokov "асинхронная операция, инициируемая вызовом WSARecv/WSASend, может завершиться РАНЬШЕ и соответственно запись на IOCP о завершении мы можем получить РАНЬШЕ, чем сама функция WSARecv/WSASend вернет управление"
Правильно. Надо понимать, что внутри WSARecv/WSASend есть много кода. Теперь перечитываем верхнее. И принимаем как факт то, что после прихода завершения в обработчик, входные параметры этими функциями не используются, хотя возврат из них может ещё не произойти.
Т.е. для нас фактически получается: P>Gomes "Обработчик вызывается только после завершения WSARecv/WSASend, иначе быть не может."
То, что где-то у кого-то что-то валится — это исключительно ошибки в коде.
Re[6]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Armastab, Вы писали:
A>>Здравствуйте, Аноним, Вы писали:
А>>>ну все просто А>>>1) создал (достал из пула) структуру Overlapped с "хвостом" А>>>2) передал в, скажем, WSARecv() А>>>3) проверил возврат, ноль или не ноль и ERROR_IO_PENDING — значит жди события на IOCP А>>>иначе грохай структуру (возвращай в пул) А>>>Примечание: в момент проверки кода возврата, в случае безошибочности, событие может уже и наступить и быть обработанным, но, поскольку, ответ будет положительным то ничего со структурой делать нельзя — она отдана обработчику, ну а если ошибка, то в момент проверки мы точно знаем что события не наступило и не наступит, и со структурой можно что-то делать А>>>4) в обработчике события обрабатывай структуру и код ошибки а затем грохай структуру (возвращай в пул)
A>>Именно так я все и делал, только не использовал пул, а создавал/разрушал. Именно в такой ситуации и возникала, та самая "странная" ошибка .
А>тогда стратегически все верно, ищи ошибку в коде
вот ещё раз прошу, показать декларацию CIOReq, помоему грохаться может из-за того что, что-то не то с этим классом.
возможные варианты
1. класс неунаследован от OVERLAPPED )) ну это врядли, потому что детский сад
2. класс унаследован от OVERLAPPED, но OVERLAPPED не первый в списке.
3. структура OVERLAPPED не обнуляется перед использованием, точно не скажу надо ли оно, но у меня в проекте обнуляется, это надо спросить кто точно химичил с обнулением, и как оно влияет на это.
4. CIOReq гдето reinterpret_cast'ируется в какойнибудь родительский класс, вместо static_cast'a. ну это так мысля в слух, как пример того что гдето OVERLAPPED коцается.
Re[5]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Armastab, Вы писали:
A>Происходит "преждевременное" срабатывание обработчика — вызов WSARecv еще не завершен.
Нету никаких "преждевременных" срабатываний. Ищи ошибки.
Re[14]: Исключение Access violation в WSASend и WSARecv (IOC
Все говорят об одном и том же разными словами. P> тезис от Michael Chelnokov "асинхронная операция, инициируемая вызовом WSARecv/WSASend, может завершиться РАНЬШЕ и соответственно запись на IOCP о завершении мы можем получить РАНЬШЕ, чем сама функция WSARecv/WSASend вернет управление"
Он имеет ввиду что обработчик может начать выполняться в другом потоке раньше чем выполнится инструкция, следующая за WSARecv/WSASend
P>тот же Gomes "Обработчик вызывается только после завершения WSARecv/WSASend, иначе быть не может. "
Раньше чем началась операция WSARecv/WSASend началась обработчик вызван быть не может.
Исключение Access violation в WSASend и WSARecv (IOCP)
Добрый день,
Я столкнулся со следующей проблемой. Есть 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 происходит нарушение доступа.
Вопросы:
как сигнал о завершении ввода-вывода может поступать до завершения асинхронной функции ввода-вывода,
почему это исключение не отлавливается стандартными средствами обработки исключений
что с этим делать?
Заранее спасибо.
Re: Исключение Access violation в WSASend и WSARecv (IOCP)
в качестве передатчика / приемника рутинам WSASend()/WSARecv() соответственно требуется массив WSABUF структур — его надо по любому тащить до завершения асинхронной операции
вот с этим мне сдается у вас нелады, потому как механика простая на самом деле и пашет безотказно у меня к слову уже с месяц круглосуточно
попробуйте именно динамически брать память под WSABUF на каждом вызове WSASend()/WSARecv() — освобождая ее только на следующем таком же вызове — переразмещение
ну и конечно же overlapped надо тож тащить на завершение вызова целочкой
Re[2]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
P>в качестве передатчика / приемника рутинам WSASend()/WSARecv() соответственно требуется массив WSABUF структур — его надо по любому тащить до завершения асинхронной операции P>вот с этим мне сдается у вас нелады, потому как механика простая на самом деле и пашет безотказно у меня к слову уже с месяц круглосуточно P>попробуйте именно динамически брать память под WSABUF на каждом вызове WSASend()/WSARecv() — освобождая ее только на следующем таком же вызове — переразмещение P>ну и конечно же overlapped надо тож тащить на завершение вызова целочкой
Вроде так и делаю... WSABUF у меня живет в классе CIOReq, наследнованном от OVERLAPPED, поэтому должен жить столько же, сколько и сама структура. Я динамически выделяю память под CIOReq и соответственно освобождаю ее в единственном месте — обработчике завершения ввода-вывода.
В любом случае, спасибо за идеи, буду продолжать копать...
Re[2]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, xentry, Вы писали:
X>Здравствуйте, Armastab, Вы писали:
A>>Иногда (при указанной нагрузке 20 клиентов, в среднем раз в 30 секунд, иногда чаще, иногда реже), WSASend и WSARecv вываливаются с исключением 0x00000005 Access violation. A>>При этом поля класса pIOReq оказываются невалидными, как будто объект удален. Данное исключение выскакивает в отладчике и не перехватывается ни try-catch ни __try — __except X>Вероятно в этот момент удалена структура CIOReq или сами буфера чтения/записи. Поскольку сама асинхронная операция в этот момент выполняется не в рабочем потоке процесса система выплевывает исключение которое не будет поймано. Или будет поймано "без стека", или вы увидите на экране "Приложение выполнило недопустимую операцию и будет закрыто", если отладки не было.
О, спасибо. Мне в голову как-то даже не пришло, что операция не в рабочем потоке выполняется.
A>>Экспериментально выяснилось, если количество рабочих потоков сделать равным 1 (обычно запущено 10), такой ошибки не возникает. A>>Если сделать защиту (собственный механизм) указателя pIOReq от удаления, до возврата из WSASend, WSARecv, то ошибки тоже не возникает, а отлавливается попытка удалить объект до снятия защиты. X>Это потому что в одном потоке все вызовы будут сериализированы.
Ага, до это я догадался.
A>>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv. A>>Он удаляет объект pIOReq и в WSASend/WSARecv происходит нарушение доступа. X>Тут сложно сказать наверняка, не видя кода, но это предположение скорее всего ошибочное.
В данный момент удаление структуры (по крайней мере оператор delete) CIOReq происходит в единственном месте — рабочем потоке, после того как он получает сигнал о завершении операции ввода/вывода, именно в этом месте наблюдается переодическая попытка удаления структуры, защищенной от удаления, хотя, конечно, это теоретически может происходить и в промежуток между командой WSARecv и следующим за ней снятием защиты.
X>Отлаживать Стоит подумать о счетчике ссылок в CIOReq (раз уж есть механизм защиты от его удаления)
Ну, собственно, механизм защиты и реализован через примитивный счетчик ссылок, правда не в самом CIOReq а во внешнем объекте. Это, конечно, избавляет от исключений, но что-то мне подсказывает, что такой ошибки быть не должно. Спасибо за информацию, буду отлаживать.
Re[2]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Здравствуйте, Armastab, Вы писали:
A>>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv.
MC>Такая ситуация вполне реальна и происходит достаточно часто, особенно на многопроцессорных системах. Я обычно делаю счетчик ссылок, инкрементирую его перед вызовом WSASend/WSARecv, а декрементирую в обработчике IOCP или в случае ошибки WSASend/WSARecv (не-IO_PENDING, т.е. когда обработчик вызываться не будет).
и какое количество переданных/полученных байт возвращается на таком 'преждевременном' завершении отсылки/получения ?
Re[2]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Здравствуйте, Armastab, Вы писали:
A>>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv. MC>Такая ситуация вполне реальна и происходит достаточно часто, особенно на многопроцессорных системах. Я обычно делаю счетчик ссылок, инкрементирую его перед вызовом WSASend/WSARecv, а декрементирую в обработчике IOCP или в случае ошибки WSASend/WSARecv (не-IO_PENDING, т.е. когда обработчик вызываться не будет).
Спасибо большое! А то я уже устал отлаживать... Есть вопрос про Ваш механизм счетчика ссылок.
Я делаю следующим образом:
1) перед вызовом WSASend/WSARecv увеличиваю счетчик ссылок на струтуру OVERLAPPED
2) после вызова WSASend/WSARecv уменьшаю счетчик ссылок на струтуру OVERLAPPED
3) В обработчике перед удалением структуры OVERLAPPED проверяю, если счетчик ссылок не 0, то жду пока он станет 0, т.о. я удостовериваюсь, что произошел возврат из WSASend/WSARecv и удаление объекта не приведет к ошибке.
Я не совсем понял Ваш алгоритм работы, если счетчик инкрементировать перед асинхронным вызовом, а декрементировать только в обработчике, каким образом это может защитить от разрушения структуры OVERLAPPED до завершения WSASend\WSARecv ? Или идея в чем-то другом?
Re[3]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
P>Здравствуйте, Michael Chelnokov, Вы писали:
MC>>Здравствуйте, Armastab, Вы писали:
A>>>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv.
MC>>Такая ситуация вполне реальна и происходит достаточно часто, особенно на многопроцессорных системах. Я обычно делаю счетчик ссылок, инкрементирую его перед вызовом WSASend/WSARecv, а декрементирую в обработчике IOCP или в случае ошибки WSASend/WSARecv (не-IO_PENDING, т.е. когда обработчик вызываться не будет).
P> P>и какое количество переданных/полученных байт возвращается на таком 'преждевременном' завершении отсылки/получения ?
У меня возвращается количество байт, которое было получено. Тестирующий клиент посылает 3 байта. В момент таких "странных" срабатываний обработчика вызова WSARecv возвращается 3 байта.
Re[4]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Armastab, Вы писали:
A>Здравствуйте, Pepel, Вы писали:
P>>Здравствуйте, Michael Chelnokov, Вы писали:
MC>>>Здравствуйте, Armastab, Вы писали:
A>>>>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv.
MC>>>Такая ситуация вполне реальна и происходит достаточно часто, особенно на многопроцессорных системах. Я обычно делаю счетчик ссылок, инкрементирую его перед вызовом WSASend/WSARecv, а декрементирую в обработчике IOCP или в случае ошибки WSASend/WSARecv (не-IO_PENDING, т.е. когда обработчик вызываться не будет).
P>> P>>и какое количество переданных/полученных байт возвращается на таком 'преждевременном' завершении отсылки/получения ?
A>У меня возвращается количество байт, которое было получено. Тестирующий клиент посылает 3 байта. В момент таких "странных" срабатываний обработчика вызова WSARecv возвращается 3 байта.
я так понимаю странность в том, что за ним следует точно такое же срабатывание — которое, поскольку оно последнее, является вроде как настоящим ?
Re[5]: Исключение Access violation в WSASend и WSARecv (IOCP
и как в такой ситуации помогают некие счетчики ссылок — я понимаю есть псевдосрабатывание завершения некой асинхронной операции, которое тем и отличается от настоящего, что находится на самом деле еще в работе и посему одновременное обращение к конструкциям данного асинхронного вызова вызывает нарушение доступа
тогда только в __try — catch() брать обработчик завершения отсылки/получения и если ловим ACCESS_VIOLATION — игнорируем его, полагая , что код вменяемый и нарушение доступа по иной причине маловероятно
Re[3]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Armastab, Вы писали:
A>Я делаю следующим образом:
Не надо так делать. Делай как сказано: инкремент до, декремент в обработчике (или при ошибке). Это наглядно и логично.
A>Я не совсем понял Ваш алгоритм работы, если счетчик инкрементировать перед асинхронным вызовом, а декрементировать только в обработчике, каким образом это может защитить от разрушения структуры OVERLAPPED до завершения WSASend\WSARecv ? Или идея в чем-то другом?
Не понятно что не понятно. Структуру ты удаляешь сам, в обработчике, по счетчику == 0.
Re[5]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
A>>>>>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv. MC>>>>Такая ситуация вполне реальна и происходит достаточно часто, особенно на многопроцессорных системах. Я обычно делаю счетчик ссылок, инкрементирую его перед вызовом WSASend/WSARecv, а декрементирую в обработчике IOCP или в случае ошибки WSASend/WSARecv (не-IO_PENDING, т.е. когда обработчик вызываться не будет). P>>>и какое количество переданных/полученных байт возвращается на таком 'преждевременном' завершении отсылки/получения ? A>>У меня возвращается количество байт, которое было получено. Тестирующий клиент посылает 3 байта. В момент таких "странных" срабатываний обработчика вызова WSARecv возвращается 3 байта. P>я так понимаю странность в том, что за ним следует точно такое же срабатывание — которое, поскольку оно последнее, является вроде как настоящим ?
Нет, странность не в этом. Точно такого же срабатывания не следует. На один динамически выделяемый объект OVERLAPPED, передаваемый в асинхронный вызов WSARecv/WSASend, следует одно срабатываение обработчика вызовов. В обработчике я разрушаю объект OVERLAPPED. Странность в том, что срабатывание обработчика, по моему мнению, происходит до того, как WSARecv/WSASend закончили свою работу и вернули управление в вызывающий их поток. Т.к. WSARecv/Send еще не отработал до конца, а OVERLAPPED уже рарзушено в другом процессе внезапно сработавшим обработчиком, возникает исключение.
Выводы о "преждевременном" срабатывании обработчика я сделал на основании экспериментов с уменьшением количества рабочих потоков до 1 (ошибки не возникает, т.к. нет работы нескольких потоков, вызовы сериализуются), и организацией счетчика ссылок на структуру OVERLAPPED ( увеличение счетчика перед асинхронным вызовом, уменьшение его после, ожидание обнуление счетчика перед удалением структуры — наблюдаются попытки удаления при ненулевом счетчике, но оно блокируются и ошибки не возникает). Возможно, я где-то ошибаюсь и такое "странное" поведение программы обусловлено не найдеными мною багами.
Re[6]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
P>и как в такой ситуации помогают некие счетчики ссылок — я понимаю есть псевдосрабатывание завершения некой асинхронной операции, которое тем и отличается от настоящего, что находится на самом деле еще в работе и посему одновременное обращение к конструкциям данного асинхронного вызова вызывает нарушение доступа
Это что за оккультизм?
P>тогда только в __try — catch() брать обработчик завершения отсылки/получения и если ловим ACCESS_VIOLATION — игнорируем его, полагая , что код вменяемый и нарушение доступа по иной причине маловероятно
Ужос-ужос.
Re[6]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
P>и как в такой ситуации помогают некие счетчики ссылок — я понимаю есть псевдосрабатывание завершения некой асинхронной операции, которое тем и отличается от настоящего, что находится на самом деле еще в работе и посему одновременное обращение к конструкциям данного асинхронного вызова вызывает нарушение доступа
Счетчики ссылок помогают защитить объект от преждевременного удаления (см. соседние комментарии)
P>тогда только в __try — catch() брать обработчик завершения отсылки/получения и если ловим ACCESS_VIOLATION — игнорируем его, полагая , что код вменяемый и нарушение доступа по иной причине маловероятно
Я пробовал — try-catch на WSARecv/WSASrnd не ловит это исключение. Xentry подсказал, что это может быть из-за того, что выполнение асинхронных функций происходит не в вызывающем потоке.
В обработчике ловить это исключений не додумался — попробую. Спасибо.
Re: Исключение Access violation в WSASend и WSARecv (IOCP)
Здравствуйте, Gomes, Вы писали:
G>Здравствуйте, Armastab, Вы писали:
A>>Я делаю следующим образом: G>Не надо так делать. Делай как сказано: инкремент до, декремент в обработчике (или при ошибке). Это наглядно и логично.
A>>Я не совсем понял Ваш алгоритм работы, если счетчик инкрементировать перед асинхронным вызовом, а декрементировать только в обработчике, каким образом это может защитить от разрушения структуры OVERLAPPED до завершения WSASend\WSARecv ? Или идея в чем-то другом? G>Не понятно что не понятно. Структуру ты удаляешь сам, в обработчике, по счетчику == 0.
Если я делаю инкремент до вызова WSARecv- счетчик становиттся равным 1. Происходит "преждевременное" срабатывание обработчика — вызов WSARecv еще не завершен. В обработчике я делаю декремент — счетчик равен 0. Я удалю структуру — возникает ошибка т.к. WSARecv еще не завершился и использует структуру. Где профит?
Я, видимо, что-то не понимаю в алгоритме работы со счетчиками, поясните пожалуйста.
Re[7]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
P>и как в такой ситуации помогают некие счетчики ссылок — я понимаю есть псевдосрабатывание завершения некой асинхронной операции, которое тем и отличается от настоящего, что находится на самом деле еще в работе и посему одновременное обращение к конструкциям данного асинхронного вызова вызывает нарушение доступа
Скорее всего там нет никакого псевдосрабатывания — я думаю что топикстартер не разобрался доконца в механизме работы. Счетчик ссылок может помочь например при закрытии сокета — т.к. это может вызвать завершение асинхронных операций (если они конечно были).
P>тогда только в __try — catch() брать обработчик завершения отсылки/получения и если ловим ACCESS_VIOLATION — игнорируем его, полагая , что код вменяемый и нарушение доступа по иной причине маловероятно
В обрабочике ловить ACCESS_VIOLATION будет поздно — приложение к этому моменту уже вылетит в отладчик.
Re[7]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Gomes, Вы писали:
G>Здравствуйте, Armastab, Вы писали:
A>>Странность в том, что срабатывание обработчика, по моему мнению, происходит до того, как WSARecv/WSASend закончили свою работу и вернули управление в вызывающий их поток. Т.к. WSARecv/Send еще не отработал до конца, а OVERLAPPED уже рарзушено в другом процессе внезапно сработавшим обработчиком, возникает исключение. G>Ерунда. Обработчик вызывается только после завершения WSARecv/WSASend, иначе быть не может. Может тебе так кажется на двух ядрах? G>В обработчике можешь смело удалять структуру. Если вылазит ошибка — ищи баг.
Ну, собственно говоря, мой вопрос и преследовал цель выяснить, это мне так кажется на двух ядрах ( к этому варианту я изначально и склонялся) или, действительно, такое явление в природе существует.
Изначально я был уверен, что где-то у меня глюки, но после ответа Michael Chelnokov стал думать, что такая ситуация (с преждевременным срабатыванием обработчика) случается и надо просто принимать ее как нормальное явление и работать с ней через защиту объектов от преждевременного удаления
Re[6]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Armastab, Вы писали:
A>Ну, собственно говоря, мой вопрос и преследовал цель выяснить, это мне так кажется на двух ядрах ( к этому варианту я изначально и склонялся) или, действительно, такое явление в природе существует.
20 постов непонятно для чего. Надо спрашивать прямо и понятно, так же и ответят
Re[8]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Armastab, Вы писали:
A>Изначально я был уверен, что где-то у меня глюки, но после ответа Michael Chelnokov стал думать, что такая ситуация (с преждевременным срабатыванием обработчика) случается и надо просто принимать ее как нормальное явление и работать с ней через защиту объектов от преждевременного удаления
нормальное явление ???? где это описано, это из разряда "наши гранаты супер, но каждая 20я взрывается в руках " ..,
вот б ссылочку на MS — описание бага и методы борьбы
Re[7]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
P>да, к слову , а код возврата WSARecv какой в таком раскладе ?
Не понял, при каком раскладе? Стандартно ERROR_IO_PENDING.
Re[7]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, xentry, Вы писали:
X>Здравствуйте, Pepel, Вы писали:
P>>и как в такой ситуации помогают некие счетчики ссылок — я понимаю есть псевдосрабатывание завершения некой асинхронной операции, которое тем и отличается от настоящего, что находится на самом деле еще в работе и посему одновременное обращение к конструкциям данного асинхронного вызова вызывает нарушение доступа
X>Скорее всего там нет никакого псевдосрабатывания — я думаю что топикстартер не разобрался доконца в механизме работы. Счетчик ссылок может помочь например при закрытии сокета — т.к. это может вызвать завершение асинхронных операций (если они конечно были).
P>>тогда только в __try — catch() брать обработчик завершения отсылки/получения и если ловим ACCESS_VIOLATION — игнорируем его, полагая , что код вменяемый и нарушение доступа по иной причине маловероятно
X>В обрабочике ловить ACCESS_VIOLATION будет поздно — приложение к этому моменту уже вылетит в отладчик.
Ага, попробовал — там тоже не ловится. Этого следовало ожидать, но я уже согласен на любый идеи, которые могут как-то помочь разобраться в ситуации
Re[7]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
P>да, к слову , а код возврата WSARecv какой в таком раскладе ?
В ситуациях без исключения SOCKET_ERROR, WSA_IO_PENDING, а когда возникает исключение, то никакого кода возврата нет, т.к.WSARecv разорвало исключением.
Re[8]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
P>я к слову вот overlapped не разрушаю, а обнуляю на обработчике завершения (memeset(..))
P>а вообщем чтот здесь странно , я так понял у вас это не редкость — такая ситуевина, тогда это черти че , мож патчи накатайте на операционку
Я проводил тестирование на нескольких не моих серверах на IOCP — там такой ошибки не возникает, но ни один из них не разрушает OVERLAPPED. Во всех реализовано повторное использование памяти, т.е. те же структуры отправляются в очередь свободных структур и обнуляются при последющем использовании. Я тоже собираюсь в будущем так сделать, но, как мне кажется, это вылечит следствия проблемы, а не ее причину, т.к. если у меня где-то есть ошибка, то она останется, просто будет реализован механизм защиты от ее последствий.
Патчи...винда каждый день скачивает кучу какого-то барахла и устанавливает, так что, мне кажется, что все последние обновления присутствуют
Anyway, спасибо за советы
Re[4]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
P>вот поднял исходники, у меня исключительно под отладчиком происходило псевдосрабатывание GetQueuedCompletionStatus() и именно когда рабочих потоков более одного,
P> при этом @err = 87 (ERROR_INVALID_PARAMETER)
P> фенька была именно под отладчиком, но вот бодался пока не сообразил
Под отладчиком у меня такой ошибки не возвращается.
А вот без отладчика, исключение вроде бы не возникает (уже минут 20 как работает без вылетов), хотя попытки удалять защищенный объект в логе фиксируются, но возможно это происходит потому, что обрабочик активизируется сразу после асинхронного вызова, до выполнения команды разблокировки объекта.
Спасибо.
Re[9]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Pepel, Вы писали:
P>нормальное явление ???? где это описано, это из разряда "наши гранаты супер, но каждая 20я взрывается в руках " .., P>вот б ссылочку на MS — описание бага и методы борьбы
Никаких ошибок, вполне штатная ситуация. Где написано, что WSARecv/WSASend должны выполняться атомарно со следующей строкой на C?
С точки зрения ядра начало операции ввода/вывода уже прошло. Ядро не интересует, выполнилась ли уже на пользовательском уровне инструкция ret, или следующий за ней код.
Re[10]: Исключение Access violation в WSASend и WSARecv (IOC
я так понял : асинхронная операция, инициируемая вызовом WSARecv/WSASend, может завершиться РАНЬШЕ, чем сама функция WSARecv/WSASend вернет управление и по этой причине обработчик завершения может грохнуться , ну понятно почему
это реально правда ?
но тогда какие счетчики ? нужна синхронизация полноценная , евенты теж — выставляем евент по возврату из WSARecv/WSASend , а на обработчике завершения ждем пока евент в UP не станет
...
и вообщем странно, что такие .. не ну гвозди .. и нигде не описаны
Re: Исключение Access violation в WSASend и WSARecv (IOCP)
Здравствуйте, Armastab, Вы писали:
A>Добрый день, A>Заранее спасибо.
у вас ещё больше проблемм чем вы думаете.
для начала, зачем все время делать new и delete для буферов? именно из-за такой модели у вас и куча проблемм.
сделайте пул, или возьмите тот-же SLIST http://msdn.microsoft.com/en-us/library/ms686309(VS.85).aspx
запихайте в него new CIOReq'ов столько сколько нужно для полной загрузки
и когда надо берите из пула буфер, и после обработки возвращайте буфер в пул.
итого нету жрущих проц new delete, и никаких access viloation
Re[2]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, maxlosyam, Вы писали:
M>Здравствуйте, Armastab, Вы писали:
A>>Добрый день, A>>Заранее спасибо.
M>у вас ещё больше проблемм чем вы думаете. M>для начала, зачем все время делать new и delete для буферов? именно из-за такой модели у вас и куча проблемм.
спасибо, что обратили внимание. Я знаю про эту проблему и следующим шагом как раз собирался реализовать повторное использование памяти, просто пока отлаживал именно в вышеописанном варианте.
Re: Исключение Access violation в WSASend и WSARecv (IOCP)
От:
Аноним
Дата:
01.07.09 16:48
Оценка:
Здравствуйте, Armastab, Вы писали:
A>Добрый день, A>Я столкнулся со следующей проблемой. Есть TCP-сервер построенный на технологии портов завершения ввода-вывода. Есть 20 клиентов, которые в целях тестирования непрерывно выполняют следующие команды: Connect, Send (3байта), Disconnect. Клиенты запущены на той же машине, что и сервер.
A>Основная функция рабочего потока сервера выглядит стандартно для IOCP, примерно так:
A>void WorkerThread::Run() A>{
A> ... A> while(true) A> { A> ... A> fOk = m_refIOCP.GetStatus(&CompKey,&dwNumBytes, (OVERLAPPED**)&pIOReq); A> ... A> HandleOperation(CompKey, pIOReq, dwNumBytes); A> ... A> delete pIOReq; A> .. A> } A> ... A>}
A>Есть класс CIOReq наследованный от OVERLAPPED, который несет дополнительную информацию об операциях. A>Функция HandleOperation имеет некоторую логику и делает следующие вызовы:
A>1. A>... A>pIOReq = new CIOReq(); A>... A>int nRes = WSASend(socket, pWSABUF , 1, &dwLen, dwFlags, (OVERLAPPED*)pIOReq, NULL);
A>2. A>... A>pIOReq = new CIOReq(); A>... A>nRes = WSARecv(socket, pWSABUF, 1, &dwSize, &dwFlags,(OVERLAPPED*)pIOReq , NULL);
A>Иногда (при указанной нагрузке 20 клиентов, в среднем раз в 30 секунд, иногда чаще, иногда реже), WSASend и WSARecv вываливаются с исключением 0x00000005 Access violation. A>При этом поля класса pIOReq оказываются невалидными, как будто объект удален. Данное исключение выскакивает в отладчике и не перехватывается ни try-catch ни __try — __except
A>Экспериментально выяснилось, если количество рабочих потоков сделать равным 1 (обычно запущено 10), такой ошибки не возникает. A>Если сделать защиту (собственный механизм) указателя pIOReq от удаления, до возврата из WSASend, WSARecv, то ошибки тоже не возникает, а отлавливается попытка удалить объект до снятия защиты.
A>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv. A>Он удаляет объект pIOReq и в WSASend/WSARecv происходит нарушение доступа.
A>Вопросы: A>как сигнал о завершении ввода-вывода может поступать до завершения асинхронной функции ввода-вывода, A>почему это исключение не отлавливается стандартными средствами обработки исключений A>что с этим делать?
A>Заранее спасибо.
Судя по этим строчкам, вы просто производите удаление объекта pIOReq, который же является OVERLAPPED структурой, до завершения асинхронной операции. А точно знать, что она завершилась, можно тогда, когда WSASend() вернула 0, или установилось событие hEvent из переданной OVERLAPPED структуры, или был бы вызван обработчик завершения lpCompletitionRoutine(), который бы устанавливался последним параметром WSASend(), но вы его не устанавливаете. Очевидно, до удаления указателя надо проверить код возврата и статус операции и, если она была отложенной, ждать события завершения...
=)
Re[10]: Исключение Access violation в WSASend и WSARecv (IOC
От:
Аноним
Дата:
01.07.09 18:20
Оценка:
Здравствуйте, Michael Chelnokov, Вы писали: MC>Никаких ошибок, вполне штатная ситуация. Где написано, что WSARecv/WSASend должны выполняться атомарно со следующей строкой на C? MC>С точки зрения ядра начало операции ввода/вывода уже прошло. Ядро не интересует, выполнилась ли уже на пользовательском уровне инструкция ret, или следующий за ней код.
Мда, открываются новые аспекты...
Возможно теперь я разберусь, почему у меня иногда валится приложение, несмотря на попытку сохранять буферы подсчетом ссылок.
Насколько я понял, схема должна быть приблизительно такая:
void WorkerThread::Run(){
while( true ){
fOk = m_refIOCP.GetStatus( &CompKey, &dwNumBytes, (OVERLAPPED**)&pIOReq );
HandleOperation( CompKey, pIOReq, dwNumBytes );
// если функция WSASend/WSARecv вернула управление до того,
// как система обработала запрос и переключилась в поток обработчика - удаление,
// иначе - уменьшение счетчика
pIOReq->Release();
}
}
...
void HandleOperation(...){
...
pIOReq = new CIOReq();
// дважды увеличиваем счетчик ссылок
pIOReq->AddRef(); // соответсвует Release() после WSASend()
pIOReq->AddRef(); // соответсвует Release() после HandleOperation()int nRes = WSASend( socket, pWSABUF , 1, &dwLen, dwFlags, (OVERLAPPED*)pIOReq, NULL );
// если HandleOperation вернула управление, обработав операцию раньше возврата
// из асинхронной функции - удаление, иначе - уменьшение счетчика
pIOReq->Release();
...
pIOReq = new CIOReq();
pIOReq->AddRef();
pIOReq->AddRef();
nRes = WSARecv( socket, pWSABUF, 1, &dwSize, &dwFlags,(OVERLAPPED*)pIOReq , NULL );
// если HandleOperation вернула управление, обработав операцию раньше возврата
// из асинхронной функции - удаление, иначе - уменьшение счетчика
pIOReq->Release();
...
}
?
Re[11]: Исключение Access violation в WSASend и WSARecv (IOC
От:
Аноним
Дата:
01.07.09 18:31
Оценка:
забыл добавить:
void HandleOperation(...){
...
pIOReq = new CIOReq();
// дважды увеличиваем счетчик ссылок
pIOReq->AddRef(); // соответсвует Release() после WSASend()
pIOReq->AddRef(); // соответсвует Release() после HandleOperation()int nRes = WSASend( socket, pWSABUF , 1, &dwLen, dwFlags, (OVERLAPPED*)pIOReq, NULL );
if (nRes == SOME_ERROR && nRes != IO_PENDING)
pIOReq->Release();// если HandleOperation вернула управление, обработав операцию раньше возврата
// из асинхронной функции - удаление, иначе - уменьшение счетчика
pIOReq->Release();
...
pIOReq = new CIOReq();
pIOReq->AddRef();
pIOReq->AddRef();
nRes = WSARecv( socket, pWSABUF, 1, &dwSize, &dwFlags,(OVERLAPPED*)pIOReq , NULL );
if (nRes == SOME_ERROR && nRes != IO_PENDING)
pIOReq->Release();// если HandleOperation вернула управление, обработав операцию раньше возврата
// из асинхронной функции - удаление, иначе - уменьшение счетчика
pIOReq->Release();
...
}
Re[11]: Исключение Access violation в WSASend и WSARecv (IOC
Так, отставить. Со счетчиками мы тебе прогнали Ты же защищаешь не PerConnection, а PerIo. Тут железно: перед WSASend/WSARecv выделил, в обработчике удалил. Без вариантов. Так что какая-то бага изначально у тебя. Счетчики пока убирай — потом понадобятся.
Вот такой вопросик, чиста удостовериться: вот сюда "void HandleOperation(...)" указатель на CIOReq под каким именем передается? И что ты с ним делаешь?
Re[2]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Аноним, Вы писали:
А>Судя по этим строчкам, вы просто производите удаление объекта pIOReq, который же является OVERLAPPED структурой, до завершения асинхронной операции. А точно знать, что она завершилась, можно тогда, когда WSASend() вернула 0, или установилось событие hEvent из переданной OVERLAPPED структуры, или был бы вызван обработчик завершения lpCompletitionRoutine(), который бы устанавливался последним параметром WSASend(), но вы его не устанавливаете. Очевидно, до удаления указателя надо проверить код возврата и статус операции и, если она была отложенной, ждать события завершения... А>=)
вообщето это к IOCP не относится, субж бы хотябы прочитали.
Re[12]: Исключение Access violation в WSASend и WSARecv (IOC
Здравствуйте, Аноним, Вы писали:
А>забыл добавить:
слушайте, а не могли бы вы привести декларацию класса CIOReq?
просто по первому посту все у вас нормально.
если валится на WSARecv не должно никак, не там ищете думаю.
Re[13]: Исключение Access violation в WSASend и WSARecv (IOC
главный вопрос здесь уже не частная конкретика иницииатора ветки полагаю, а тезис от Michael Chelnokov "асинхронная операция, инициируемая вызовом WSARecv/WSASend, может завершиться РАНЬШЕ и соответственно запись на IOCP о завершении мы можем получить РАНЬШЕ, чем сама функция WSARecv/WSASend вернет управление"
у меня данный расклад не учитывается, но и влеты в нарушения доступа к памяти единичные некие бывают таки
часть же коллег, сообщает, что такого быть не могеть , тот же Gomes "Обработчик вызывается только после завершения WSARecv/WSASend, иначе быть не может. "
вообщем мне все-таки странно осознавать, что в порт завершения ввода-вывода ставится запись о завершении асинхронной операции, в то время как ф-ция ее старта (WSARecv/WSASend) еще использует структуры асинхронного вызова, понятно, когда прапор орет "смирррна, круугггом " и он еще рот не закрыл , а все уже повернулись, но здесь ж думается трезвые люди писали концепт асинхроники этой всей ...
по итогу получается надо дорабатывать код и ставить защиту от такой вот особенности, так я понимаю ?
Re[15]: Исключение Access violation в WSASend и WSARecv (IOC
Здравствуйте, xentry, Вы писали:
>Он имеет ввиду что обработчик может начать выполняться в другом потоке раньше чем >выполнится инструкция, следующая за WSARecv/WSASend
это конечно .. значит я не так понял его пояснение, тогда все отлично, конечно же в мультизадачной среде это норма вещей
Re[15]: Исключение Access violation в WSASend и WSARecv (IOC
спасибо.. полегчало, не очень хотелось синхронизацию еще свою отстраивать на этих делах
Re[16]: Исключение Access violation в WSASend и WSARecv (IOC
От:
Аноним
Дата:
06.07.09 16:10
Оценка:
Здравствуйте, Pepel, Вы писали: P> спасибо.. полегчало, не очень хотелось синхронизацию еще свою отстраивать на этих делах
А я бы не стал верить ни уважаемому Гомесу, ни Микрософту.
Приведите пожалуйста выдержку из какого нибудь документа, где сказано, что операция WSASend/WSARecv выполняется атомарно по отношению к обработчику завершения?
На многоядерных машинах, да и еще в таком абсолютно непредсказуемом (по отношению к переключению контекста внутренних потоков) механизме, как IOCP, вполне можно ожидать, что обработчик может позваться еще до инструкции ret из WSASend/WSARecv.
И никто не даст гарантию, что после постановки запроса на выполнение операции и до выхода из WSASend/WSARecv данные функции ничего не делают с переданным в них буфером (там могут быть по крайней мере какие нибудь "невинные" проверки).
Самое интересное, по моим подсчетам, как минимум трое достаточно грамотных и опытных людей, сообщили о неких "ложных срабатываниях" и непонятных поломках то ли в дебаге, то ли еще где то.
Неужели это не повод перестраховаться?
Как говорится, лучше перебдеть, имхо.
Re[17]: Исключение Access violation в WSASend и WSARecv (IOC
Здравствуйте, Аноним, Вы писали:
А>И никто не даст гарантию, что после постановки запроса на выполнение операции и до выхода из WSASend/WSARecv данные функции ничего не делают с переданным в них буфером (там могут быть по крайней мере какие нибудь "невинные" проверки).
Не, все проверки гарантировано заканчиваются до возникновения уведомления о завершении операции ввода/вывода. Это следует хотя бы из терминологии.
Re[17]: Исключение Access violation в WSASend и WSARecv (IOC
Здравствуйте, Аноним, Вы писали:
А>А я бы не стал верить ни уважаемому Гомесу, ни Микрософту.
По вопросам веры — в церковь (с) Гоблин ;)
А>Приведите пожалуйста выдержку из какого нибудь документа, где сказано, что операция WSASend/WSARecv выполняется атомарно по отношению к обработчику завершения?
По-твоему они должны писать документ на любую бердовую мысль, которая может возникнуть у пользователя?
А>И никто не даст гарантию, что после постановки запроса на выполнение операции и до выхода из WSASend/WSARecv данные функции ничего не делают с переданным в них буфером (там могут быть по крайней мере какие нибудь "невинные" проверки).
Давай не надо ерунду писать.
А>Самое интересное, по моим подсчетам, как минимум трое достаточно грамотных и опытных людей, сообщили о неких "ложных срабатываниях" и непонятных поломках то ли в дебаге, то ли еще где то.
А на ошибки в компиляторе опытные люди не жаловались?
А>Неужели это не повод перестраховаться?
Да лучше в каске спать ;)
Без обид — но смешно читать.
Re: Исключение Access violation в WSASend и WSARecv (IOCP)
От:
Аноним
Дата:
09.07.09 08:57
Оценка:
Здравствуйте, Armastab, Вы писали:
A>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv. A>Он удаляет объект pIOReq и в WSASend/WSARecv происходит нарушение доступа.
A>Вопросы: A>как сигнал о завершении ввода-вывода может поступать до завершения асинхронной функции ввода-вывода, A>почему это исключение не отлавливается стандартными средствами обработки исключений A>что с этим делать?
Вот Michael Chelnokov уже правильно все написал и не один раз
Конечно, вызов обработчика IO может быть раньше чем выход из WSASend/WSARecv и иже с ними
НО! С какого перепугу нужно грохать (и вообще чего-то делать) с Overlapped и иже с ним после успешного (такого, которое породит overlapped io) вызова асинхронной функции? Отдал системе кусок памяти — не трожь! Пока система не отдаст его обратно.
Варианта всего два:
или ваш вызов WSAxxx закончился и сказал об ошибке (события не будет) — делай со структурой все что хочется (удаляй, обнуляй, возвращай в пул структур...)
или все хорошо и будет событие — вот в нем и только в нем нужно и можно работать с этой структурой
и для этого никаких счетчиков и синхронизаторов не нужно
Re[2]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Armastab, Вы писали:
A>>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv. A>>Он удаляет объект pIOReq и в WSASend/WSARecv происходит нарушение доступа.
A>>Вопросы: A>>как сигнал о завершении ввода-вывода может поступать до завершения асинхронной функции ввода-вывода, A>>почему это исключение не отлавливается стандартными средствами обработки исключений A>>что с этим делать?
А>Вот Michael Chelnokov уже правильно все написал и не один раз А>Конечно, вызов обработчика IO может быть раньше чем выход из WSASend/WSARecv и иже с ними А>НО! С какого перепугу нужно грохать (и вообще чего-то делать) с Overlapped и иже с ним после успешного (такого, которое породит overlapped io) вызова асинхронной функции? Отдал системе кусок памяти — не трожь! Пока система не отдаст его обратно. А>Варианта всего два: А>или ваш вызов WSAxxx закончился и сказал об ошибке (события не будет) — делай со структурой все что хочется (удаляй, обнуляй, возвращай в пул структур...) А>или все хорошо и будет событие — вот в нем и только в нем нужно и можно работать с этой структурой А>и для этого никаких счетчиков и синхронизаторов не нужно
Возможно, я не совсем понятно написал, но в реальности у меня Overlapped (он же CIOReq) после вызова асинхронной операции не грохается, эта структура удаляеся только в обработчике HandleOperation. По всем наблюдаемым признакам ситуация именно такая как описывает Michael Chelnokov — вызов обработчика происходит, до возврата из асинхронной операции WSARecv/WSASend. Но я все еще не исключаю багов в коде, о которых говорит Gomes.
Re[12]: Исключение Access violation в WSASend и WSARecv (IOC
Здравствуйте, Gomes, Вы писали:
G>Так, отставить. Со счетчиками мы тебе прогнали Ты же защищаешь не PerConnection, а PerIo. Тут железно: перед WSASend/WSARecv выделил, в обработчике удалил. Без вариантов. Так что какая-то бага изначально у тебя. Счетчики пока убирай — потом понадобятся. G>Вот такой вопросик, чиста удостовериться: вот сюда "void HandleOperation(...)" указатель на CIOReq под каким именем передается? И что ты с ним делаешь?
Вкратце, функция Run рабочего потока выглядит так (проверки ошибок GetLastError и т.д. для краткости вырезаны):
В HandleOperation проверяется тип операции pIOReq и создаются новые асинхронные вызовы с другими экземплярами CIOReq, при это исходный pIOReq нигде внутри HandleOperation не модифицируется. Вышеприведенный delete это единственное место уничтожения структуры CIOReq/
Re[3]: Исключение Access violation в WSASend и WSARecv (IOCP
От:
Аноним
Дата:
09.07.09 14:09
Оценка:
Здравствуйте, Armastab, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Armastab, Вы писали:
A>>>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv. A>>>Он удаляет объект pIOReq и в WSASend/WSARecv происходит нарушение доступа.
A>>>Вопросы: A>>>как сигнал о завершении ввода-вывода может поступать до завершения асинхронной функции ввода-вывода, A>>>почему это исключение не отлавливается стандартными средствами обработки исключений A>>>что с этим делать?
А>>Вот Michael Chelnokov уже правильно все написал и не один раз А>>Конечно, вызов обработчика IO может быть раньше чем выход из WSASend/WSARecv и иже с ними А>>НО! С какого перепугу нужно грохать (и вообще чего-то делать) с Overlapped и иже с ним после успешного (такого, которое породит overlapped io) вызова асинхронной функции? Отдал системе кусок памяти — не трожь! Пока система не отдаст его обратно. А>>Варианта всего два: А>>или ваш вызов WSAxxx закончился и сказал об ошибке (события не будет) — делай со структурой все что хочется (удаляй, обнуляй, возвращай в пул структур...) А>>или все хорошо и будет событие — вот в нем и только в нем нужно и можно работать с этой структурой А>>и для этого никаких счетчиков и синхронизаторов не нужно
A>Возможно, я не совсем понятно написал, но в реальности у меня Overlapped (он же CIOReq) после вызова асинхронной операции не грохается, эта структура удаляеся только в обработчике HandleOperation. По всем наблюдаемым признакам ситуация именно такая как описывает Michael Chelnokov — вызов обработчика происходит, до возврата из асинхронной операции WSARecv/WSASend. Но я все еще не исключаю багов в коде, о которых говорит Gomes.
ну все просто
1) создал (достал из пула) структуру Overlapped с "хвостом"
2) передал в, скажем, WSARecv()
3) проверил возврат, ноль или не ноль и ERROR_IO_PENDING — значит жди события на IOCP
иначе грохай структуру (возвращай в пул)
Примечание: в момент проверки кода возврата, в случае безошибочности, событие может уже и наступить и быть обработанным, но, поскольку, ответ будет положительным то ничего со структурой делать нельзя — она отдана обработчику, ну а если ошибка, то в момент проверки мы точно знаем что события не наступило и не наступит, и со структурой можно что-то делать
4) в обработчике события обрабатывай структуру и код ошибки а затем грохай структуру (возвращай в пул)
Re[4]: Исключение Access violation в WSASend и WSARecv (IOCP
Здравствуйте, Аноним, Вы писали:
А>ну все просто А>1) создал (достал из пула) структуру Overlapped с "хвостом" А>2) передал в, скажем, WSARecv() А>3) проверил возврат, ноль или не ноль и ERROR_IO_PENDING — значит жди события на IOCP А>иначе грохай структуру (возвращай в пул) А>Примечание: в момент проверки кода возврата, в случае безошибочности, событие может уже и наступить и быть обработанным, но, поскольку, ответ будет положительным то ничего со структурой делать нельзя — она отдана обработчику, ну а если ошибка, то в момент проверки мы точно знаем что события не наступило и не наступит, и со структурой можно что-то делать А>4) в обработчике события обрабатывай структуру и код ошибки а затем грохай структуру (возвращай в пул)
Именно так я все и делал, только не использовал пул, а создавал/разрушал. Именно в такой ситуации и возникала, та самая "странная" ошибка .
Re[13]: Исключение Access violation в WSASend и WSARecv (IOC
Здравствуйте, Armastab, Вы писали:
A>Вкратце, функция Run рабочего потока выглядит так (проверки ошибок GetLastError и т.д. для краткости вырезаны):
Можешь сделать минимальный тест-кейс в котором проблема воспроизводиться? Имхо это стоит потраченного времени. Иначе этот топик все больше становится похож на выездное заседание телепатов.
Re[5]: Исключение Access violation в WSASend и WSARecv (IOCP
От:
Аноним
Дата:
10.07.09 14:37
Оценка:
Здравствуйте, Armastab, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
А>>ну все просто А>>1) создал (достал из пула) структуру Overlapped с "хвостом" А>>2) передал в, скажем, WSARecv() А>>3) проверил возврат, ноль или не ноль и ERROR_IO_PENDING — значит жди события на IOCP А>>иначе грохай структуру (возвращай в пул) А>>Примечание: в момент проверки кода возврата, в случае безошибочности, событие может уже и наступить и быть обработанным, но, поскольку, ответ будет положительным то ничего со структурой делать нельзя — она отдана обработчику, ну а если ошибка, то в момент проверки мы точно знаем что события не наступило и не наступит, и со структурой можно что-то делать А>>4) в обработчике события обрабатывай структуру и код ошибки а затем грохай структуру (возвращай в пул)
A>Именно так я все и делал, только не использовал пул, а создавал/разрушал. Именно в такой ситуации и возникала, та самая "странная" ошибка .