Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.141.202.187] |
|
Страницы: (6) 1 [2] 3 4 ... Последняя » все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
progman, я привольно понимаю, что у тебя сейчас HasOverlappedIoCompleted может бесконечно вызываться ДО closesocket?
|
Сообщ.
#17
,
|
|
|
Что за объект - поточнее: 1. Это одиночная оверлапнутая структура? 2. Это буфер нескольких таких структур? 3. ???варианты... Определив что за объект, однозначно четко распознать статус самого объекта или что с ним еще может быть связано. После этого что приемлемо по статусу - убивать... Где-то так...мож что не въехал... |
Сообщ.
#18
,
|
|
|
Цитата Oleg2004 @ Do not call this macro unless the call to GetLastError returns ERROR_IO_PENDING, indicating that the overlapped I/O has started. Ну если хотя бы 1 одна операция с этой структурой overlapped была инициализирована до этого, то этот макрос должен работать нормально. Но я вообще никогда не видел в коде IOCP ее использования. И согласен с Pacific, что можно достаточно следить только за GetQueuedCompletionStatus. |
Сообщ.
#19
,
|
|
|
Цитата progman @ Вот у меня есть поток в который приходит команда - объект номер 1234 нужно убить. Как мне дальше правильно поступить? Ну как - помечаешь на удаление, вызываешь closesocket, потом (возможно в другом потоке) GetQueuedCompletionStatus вернет ошибку для текущей overlapped операции, обработчик ошибки увидит, что для этого объекта уже вызван closesocket и он помечен на удаление, и удалит его. P.S. А разве GetQueuedCompletionStatus у тебя вызываются не из выделенных под это воркеров, а из рабочего потока? Тогда это просто плохая архитектура. Под GetQueuedCompletionStatus нужно обязательно отдельные потоки, т.к. он может вернуть управление через произвольное время. |
Сообщ.
#20
,
|
|
|
А что за нужда убивать объект в отдельном потоке? Добавлено Цитата Pacific @ т.к. он может вернуть управление через произвольное время. Кстати да, я этот момент упустил. |
Сообщ.
#21
,
|
|
|
Цитата shm @ Ну если хотя бы 1 одна операция с этой структурой overlapped была инициализирована до этого, то этот макрос должен работать нормально. Но я вообще никогда не видел в коде IOCP ее использования. Она применяется в основном только для целей синхронизации Цитата Synchronization Macros The following macros are used with synchronization: HasOverlappedIoCompleted MemoryBarrier PreFetchCacheLine YieldProcessor Цитата И согласен с Pacific, что можно достаточно следить только за GetQueuedCompletionStatus. Я тоже к этому склоняюсь |
Сообщ.
#22
,
|
|
|
Цитата Oleg2004 @ Что за объект - поточнее: 1. Это одиночная оверлапнутая структура? 2. Это буфер нескольких таких структур? 3. ???варианты... Определив что за объект, однозначно четко распознать статус самого объекта или что с ним еще может быть связано. После этого что приемлемо по статусу - убивать... Где-то так...мож что не въехал... под каждого законенктившегося клиента создается объект class ovpConnection: public OVERLAPPED каждый объект заносится в список создается N рабочих потоков в которых вызывается GetQueuedCompletionStatus и обрабатываются события. проблема в том что у меня не корректно удаляются эти самые объекты. основная проблема: из другого сервера приходит запрос на удаление объекта 1234 В данный момент этот 1234 может из порта что то читать или что то писать или вообще заниматься обработкой своих внутренних данных Этот объект я заношу в очередь ожидания на удаление. В отдельном потоке эта очередь обрабатывается. и объекты удаляются дальше две ситуации: 1. я НЕ использую макрос HasOverlappedIoCompleted и ореинтируюсь исключительно на критические секции. При этом после закрытия сокета и удаления объекта 1234 в рабочем потоке может произойти вызов GetQueuedCompletionStatus а может и не произойти - я закономерность не понимаю Она по разному себя ведет. GetQueuedCompletionStatus выдаст в поле *lpOverlapped только что удаленный объект. "только что" понятие тут растяжимое может вызваться через миллисекунду а может через 3 секунды ( у меня рекорд 5 секунд был ) То что объект удален я определить уже никак не могу в этот момент - и мы падаем. 2. В потоке который обрабатывает очередь объектов на удаление я у каждого объекта уточняю статус с помощью макроса HasOverlappedIoCompleted и удаляю только те у кого нет в обработке операций Падений нет но куча объектов никогда не удаляются и очередь растет. |
Сообщ.
#23
,
|
|
|
Цитата progman @ под каждого законенктившегося клиента создается объект Честно говоря, я не понимаю внутренней причины для создания такого объекта. Может быть доцент был тупой , но в сокетных операциях оверлапедная структура указывается только в конкретных вызовах send/recv, причем для каждого конкретного вызова отдельная своя структура. Цитата progman @ я закономерность не понимаю Она по разному себя ведет. GetQueuedCompletionStatus выдаст в поле *lpOverlapped только что удаленный объект. "только что" понятие тут растяжимое может вызваться через миллисекунду а может через 3 секунды ( у меня рекорд 5 секунд был ) Ну вот надыбал что то со временными задержками (Микрософт пишет): Цитата Проблема После асинхронного ввода-вывода на жесткий диск, HasOverlappedIoCompleted возвращает TRUE, а также GetOverlappedResult() возвращает 0 байт, переданных проблемы приложения (например, Microsoft SQL Server). Примечание: После нескольких микросекунды, GetOverlappedResult() возвращает правильное значение. Причина В первую очередь эта проблема наблюдалась на компьютерах, симметричная многопроцессорная обработка (SMP), где завершения ввода/вывода обновляет поля в структуре OVERLAPPED в неверном порядке. Цитата progman @ Падений нет но куча объектов никогда не удаляются и очередь растет. Объекты на мой взгляд какие-то левые потому и ведут себя криво |
Сообщ.
#24
,
|
|
|
Цитата progman @ в рабочем потоке может произойти вызов GetQueuedCompletionStatus а может и не произойти - я закономерность не понимаю Она по разному себя ведет. А есть гарантия, что на момент закрвтия сокета есть активные операции ввода-вывода? Тут мне видится 2 ситуации: 1. Операций нет и все можно сделать прямо на месте. 2. Есть операции, объект надо пометить, сокет закрыть и ждать когда завершится последняя операция. Тут только с синхронизацией надо аккуратно. |
Сообщ.
#25
,
|
|
|
Цитата shm @ Цитата progman @ в рабочем потоке может произойти вызов GetQueuedCompletionStatus а может и не произойти - я закономерность не понимаю Она по разному себя ведет. А есть гарантия, что на момент закрвтия сокета есть активные операции ввода-вывода? Тут мне видится 2 ситуации: 1. Операций нет и все можно сделать прямо на месте. 2. Есть операции, объект надо пометить, сокет закрыть и ждать когда завершится последняя операция. Тут только с синхронизацией надо аккуратно. все замечательно - но как я узнаю что операция есть? и как я узнаю что она закончена? |
Сообщ.
#26
,
|
|
|
Цитата progman @ все замечательно - но как я узнаю что операция есть? Ты можешь для отладки сделать счетчики, как Pacific советует? Цитата progman @ и как я узнаю что она закончена? Если пришло по ней событие - значит закончена, счетчик уменьшился на 1. |
Сообщ.
#27
,
|
|
|
Цитата shm @ Цитата progman @ все замечательно - но как я узнаю что операция есть? Ты можешь для отладки сделать счетчики, как Pacific советует? Цитата progman @ и как я узнаю что она закончена? Если пришло по ней событие - значит закончена, счетчик уменьшился на 1. Надо попробовать но есть скептицизм щас займусь - как будет результат я отпишусь |
Сообщ.
#28
,
|
|
|
Тут есть есть нехорошие моменты с синхронизацией:
поток 1 установил флаг удаления объекта и закрыл сокет произошло переключения контекста на поток 2 поток 2 уменьшил значения счетчика и он стал 0. флаг удаления установлен, поэтому объект удаляется произошло переключение контекста на поток 1 поток 1 пытается проверить значения счетчика у уже разрушенного объекта со всеми вытекающими. |
Сообщ.
#29
,
|
|
|
Цитата progman @ При этом после закрытия сокета и удаления объекта 1234 в рабочем потоке может произойти вызов GetQueuedCompletionStatus а может и не произойти - я закономерность не понимаю Она по разному себя ведет. Вот обратил внимание на эту фишку - как это понять - может произойти, а может и нет? Есть код, где прописан вызов GetQueuedCompletionStatus - и в этом месте он должен произойти...как иначе то??? Или есть условие - в одном случае - вызываем, в другом - нет. но ведь и это детерминировано... Или поток сконструирован так - что гуляет по коду как хочет? Чето я архитектуру приложения недопонимаю... PS А можно кусочек кода с этими объектами class ovpConnection: public OVERLAPPED - где хранятся, как место хранения описано, как доступ к этому месту и откуда он возможен и прочее...чуть чуть... А вообще у меня большое недоверие - можно ли эту уникальную структуру объявлять в виде класса, да еще и паблик. Пару полей в ней уникальны и используются только ядром...потому и проблемы бывают, как я выше писал. |
Сообщ.
#30
,
|
|
|
Цитата Oleg2004 @ Цитата progman @ При этом после закрытия сокета и удаления объекта 1234 в рабочем потоке может произойти вызов GetQueuedCompletionStatus а может и не произойти - я закономерность не понимаю Она по разному себя ведет. Вот обратил внимание на эту фишку - как это понять - может произойти, а может и нет? Есть код, где прописан вызов GetQueuedCompletionStatus - и в этом месте он должен произойти...как иначе то??? Или есть условие - в одном случае - вызываем, в другом - нет. но ведь и это детерминировано... Или поток сконструирован так - что гуляет по коду как хочет? Чето я архитектуру приложения недопонимаю... PS А можно кусочек кода с этими объектами class ovpConnection: public OVERLAPPED - где хранятся, как место хранения описано, как доступ к этому месту и откуда он возможен и прочее...чуть чуть... А вообще у меня большое недоверие - можно ли эту уникальную структуру объявлять в виде класса, да еще и паблик. Пару полей в ней уникальны и используются только ядром...потому и проблемы бывают, как я выше писал. А я не знаю. на стороне сервера закрытие клиентского сокета может привести к срабатыванию вызова GetQueuedCompletionStatus в рабочем потоке а может нет если вызов произошел то GetQueuedCompletionStatus может вернуть FALSE и как валидный ( еще не удаленный ) указатель на OVERLAPPED так и вернуть удаленный пару секунд назад объект OVERLAPPED А может вернуть TRUE но кол-во байт 0 прочитанных в lpNumberOfBytes и аналогично или валидный указатель на OVERLAPPED или указательна только что удаленный объект. вот такая херь у меня. и как разгребать я хз. Добавлено Цитата shm @ Цитата progman @ все замечательно - но как я узнаю что операция есть? Ты можешь для отладки сделать счетчики, как Pacific советует? Цитата progman @ и как я узнаю что она закончена? Если пришло по ней событие - значит закончена, счетчик уменьшился на 1. Получается что почти все время жизни объекта счетчик операций в 1 стоит. Потому как после успешного завершения чтения или посылки данных объект вызывает чтение данных с порта и ждет когда они придут. |