На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Страницы: (6) 1 [2] 3 4 ... Последняя » все  ( Перейти к последнему сообщению )  
    > I/O Completition Port проблемы с удалением OVERLAPPED объектов
      progman, я привольно понимаю, что у тебя сейчас HasOverlappedIoCompleted может бесконечно вызываться ДО closesocket?
        Цитата progman @
        Вот у меня есть поток в который приходит команда - объект номер 1234 нужно убить.

        Что за объект - поточнее:
        1. Это одиночная оверлапнутая структура?
        2. Это буфер нескольких таких структур?
        3. ???варианты...
        Определив что за объект, однозначно четко распознать статус самого объекта или что с ним еще может быть связано.
        После этого что приемлемо по статусу - убивать...
        Где-то так...мож что не въехал... :huh:
        Сообщение отредактировано: Oleg2004 -
          Цитата 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.
            Цитата progman @
            Вот у меня есть поток в который приходит команда - объект номер 1234 нужно убить.

            Как мне дальше правильно поступить?

            Ну как - помечаешь на удаление, вызываешь closesocket, потом (возможно в другом потоке) GetQueuedCompletionStatus вернет ошибку для текущей overlapped операции, обработчик ошибки увидит, что для этого объекта уже вызван closesocket и он помечен на удаление, и удалит его.

            P.S. А разве GetQueuedCompletionStatus у тебя вызываются не из выделенных под это воркеров, а из рабочего потока? Тогда это просто плохая архитектура. Под GetQueuedCompletionStatus нужно обязательно отдельные потоки, т.к. он может вернуть управление через произвольное время.
            Сообщение отредактировано: Pacific -
              Цитата progman @
              Как мне дальше правильно поступить?

              А что за нужда убивать объект в отдельном потоке?

              Добавлено
              Цитата Pacific @
              т.к. он может вернуть управление через произвольное время.

              Кстати да, я этот момент упустил.
              Сообщение отредактировано: shm -
                Цитата shm @
                Ну если хотя бы 1 одна операция с этой структурой overlapped была инициализирована до этого, то этот макрос должен работать нормально. Но я вообще никогда не видел в коде IOCP ее использования.

                Она применяется в основном только для целей синхронизации
                Цитата
                Synchronization Macros

                The following macros are used with synchronization:
                HasOverlappedIoCompleted
                MemoryBarrier
                PreFetchCacheLine
                YieldProcessor


                Цитата
                И согласен с Pacific, что можно достаточно следить только за GetQueuedCompletionStatus.

                Я тоже к этому склоняюсь :)
                  Цитата Oleg2004 @
                  Цитата progman @
                  Вот у меня есть поток в который приходит команда - объект номер 1234 нужно убить.

                  Что за объект - поточнее:
                  1. Это одиночная оверлапнутая структура?
                  2. Это буфер нескольких таких структур?
                  3. ???варианты...
                  Определив что за объект, однозначно четко распознать статус самого объекта или что с ним еще может быть связано.
                  После этого что приемлемо по статусу - убивать...
                  Где-то так...мож что не въехал... :huh:

                  под каждого законенктившегося клиента создается объект
                  ExpandedWrap disabled
                    class ovpConnection: public OVERLAPPED

                  каждый объект заносится в список
                  создается N рабочих потоков в которых вызывается GetQueuedCompletionStatus и обрабатываются события.

                  проблема в том что у меня не корректно удаляются эти самые объекты.
                  основная проблема: из другого сервера приходит запрос на удаление объекта 1234
                  В данный момент этот 1234 может из порта что то читать или что то писать или вообще заниматься обработкой своих внутренних данных

                  Этот объект я заношу в очередь ожидания на удаление.
                  В отдельном потоке эта очередь обрабатывается.
                  и объекты удаляются

                  дальше две ситуации:
                  1. я НЕ использую макрос HasOverlappedIoCompleted и ореинтируюсь исключительно на критические секции. При этом после закрытия сокета и удаления объекта 1234 в рабочем потоке может произойти вызов GetQueuedCompletionStatus а может и не произойти - я закономерность не понимаю Она по разному себя ведет.
                  GetQueuedCompletionStatus выдаст в поле *lpOverlapped только что удаленный объект. "только что" понятие тут растяжимое может вызваться через миллисекунду а может через 3 секунды ( у меня рекорд 5 секунд был )
                  То что объект удален я определить уже никак не могу в этот момент - и мы падаем.

                  2. В потоке который обрабатывает очередь объектов на удаление я у каждого объекта уточняю статус с помощью макроса HasOverlappedIoCompleted и удаляю только те у кого нет в обработке операций
                  Падений нет но куча объектов никогда не удаляются и очередь растет.
                  Сообщение отредактировано: progman -
                    Цитата progman @
                    под каждого законенктившегося клиента создается объект

                    Честно говоря, я не понимаю внутренней причины для создания такого объекта. :no-sad: Может быть доцент был тупой :D , но в сокетных операциях оверлапедная структура указывается только в конкретных вызовах send/recv, причем для каждого конкретного вызова отдельная своя структура.
                    Цитата progman @
                    я закономерность не понимаю Она по разному себя ведет.
                    GetQueuedCompletionStatus выдаст в поле *lpOverlapped только что удаленный объект. "только что" понятие тут растяжимое может вызваться через миллисекунду а может через 3 секунды ( у меня рекорд 5 секунд был )

                    Ну вот надыбал что то со временными задержками (Микрософт пишет):
                    Цитата
                    Проблема
                    После асинхронного ввода-вывода на жесткий диск, HasOverlappedIoCompleted возвращает TRUE, а также GetOverlappedResult() возвращает 0 байт, переданных проблемы приложения (например, Microsoft SQL Server).

                    Примечание: После нескольких микросекунды, GetOverlappedResult() возвращает правильное значение.
                    Причина
                    В первую очередь эта проблема наблюдалась на компьютерах, симметричная многопроцессорная обработка (SMP), где завершения ввода/вывода обновляет поля в структуре OVERLAPPED в неверном порядке.

                    Цитата progman @
                    Падений нет но куча объектов никогда не удаляются и очередь растет.

                    Объекты на мой взгляд какие-то левые <_< потому и ведут себя криво
                    Сообщение отредактировано: Oleg2004 -
                      Цитата progman @
                      в рабочем потоке может произойти вызов GetQueuedCompletionStatus а может и не произойти - я закономерность не понимаю Она по разному себя ведет.

                      А есть гарантия, что на момент закрвтия сокета есть активные операции ввода-вывода?
                      Тут мне видится 2 ситуации:
                      1. Операций нет и все можно сделать прямо на месте.
                      2. Есть операции, объект надо пометить, сокет закрыть и ждать когда завершится последняя операция.
                      Тут только с синхронизацией надо аккуратно.
                        Цитата shm @
                        Цитата progman @
                        в рабочем потоке может произойти вызов GetQueuedCompletionStatus а может и не произойти - я закономерность не понимаю Она по разному себя ведет.

                        А есть гарантия, что на момент закрвтия сокета есть активные операции ввода-вывода?
                        Тут мне видится 2 ситуации:
                        1. Операций нет и все можно сделать прямо на месте.
                        2. Есть операции, объект надо пометить, сокет закрыть и ждать когда завершится последняя операция.
                        Тут только с синхронизацией надо аккуратно.

                        все замечательно - но как я узнаю что операция есть? и как я узнаю что она закончена?
                          Цитата progman @
                          все замечательно - но как я узнаю что операция есть?

                          Ты можешь для отладки сделать счетчики, как Pacific советует?
                          Цитата progman @
                          и как я узнаю что она закончена?

                          Если пришло по ней событие - значит закончена, счетчик уменьшился на 1.
                            Цитата shm @
                            Цитата progman @
                            все замечательно - но как я узнаю что операция есть?

                            Ты можешь для отладки сделать счетчики, как Pacific советует?
                            Цитата progman @
                            и как я узнаю что она закончена?

                            Если пришло по ней событие - значит закончена, счетчик уменьшился на 1.

                            Надо попробовать но есть скептицизм
                            щас займусь - как будет результат я отпишусь
                              Тут есть есть нехорошие моменты с синхронизацией:
                              поток 1 установил флаг удаления объекта и закрыл сокет
                              произошло переключения контекста на поток 2
                              поток 2 уменьшил значения счетчика и он стал 0. флаг удаления установлен, поэтому объект удаляется
                              произошло переключение контекста на поток 1
                              поток 1 пытается проверить значения счетчика у уже разрушенного объекта со всеми вытекающими.
                              Сообщение отредактировано: Oleg2004 -
                                Цитата progman @
                                При этом после закрытия сокета и удаления объекта 1234 в рабочем потоке может произойти вызов GetQueuedCompletionStatus а может и не произойти - я закономерность не понимаю Она по разному себя ведет.

                                Вот обратил внимание на эту фишку - как это понять - может произойти, а может и нет?
                                Есть код, где прописан вызов GetQueuedCompletionStatus - и в этом месте он должен произойти...как иначе то???
                                Или есть условие - в одном случае - вызываем, в другом - нет. но ведь и это детерминировано...
                                Или поток сконструирован так - что гуляет по коду как хочет? :wacko:
                                Чето я архитектуру приложения недопонимаю...
                                PS
                                А можно кусочек кода с этими объектами
                                class ovpConnection: public OVERLAPPED
                                - где хранятся, как место хранения описано, как доступ к этому месту и откуда он возможен и прочее...чуть чуть...
                                А вообще у меня большое недоверие - можно ли эту уникальную структуру объявлять в виде класса, да еще и паблик. :( Пару полей в ней уникальны и используются только ядром...потому и проблемы бывают, как я выше писал.
                                Сообщение отредактировано: Oleg2004 -
                                  Цитата Oleg2004 @
                                  Цитата progman @
                                  При этом после закрытия сокета и удаления объекта 1234 в рабочем потоке может произойти вызов GetQueuedCompletionStatus а может и не произойти - я закономерность не понимаю Она по разному себя ведет.

                                  Вот обратил внимание на эту фишку - как это понять - может произойти, а может и нет?
                                  Есть код, где прописан вызов GetQueuedCompletionStatus - и в этом месте он должен произойти...как иначе то???
                                  Или есть условие - в одном случае - вызываем, в другом - нет. но ведь и это детерминировано...
                                  Или поток сконструирован так - что гуляет по коду как хочет? :wacko:
                                  Чето я архитектуру приложения недопонимаю...
                                  PS
                                  А можно кусочек кода с этими объектами
                                  class ovpConnection: public OVERLAPPED
                                  - где хранятся, как место хранения описано, как доступ к этому месту и откуда он возможен и прочее...чуть чуть...
                                  А вообще у меня большое недоверие - можно ли эту уникальную структуру объявлять в виде класса, да еще и паблик. :( Пару полей в ней уникальны и используются только ядром...потому и проблемы бывают, как я выше писал.

                                  А я не знаю.
                                  на стороне сервера закрытие клиентского сокета может привести к срабатыванию вызова GetQueuedCompletionStatus в рабочем потоке а может нет
                                  если вызов произошел то GetQueuedCompletionStatus может вернуть FALSE и как валидный ( еще не удаленный ) указатель на OVERLAPPED так и вернуть удаленный пару секунд назад объект OVERLAPPED
                                  А может вернуть TRUE но кол-во байт 0 прочитанных в lpNumberOfBytes и аналогично или валидный указатель на OVERLAPPED или указательна только что удаленный объект.

                                  вот такая херь у меня. и как разгребать я хз.

                                  Добавлено
                                  Цитата shm @
                                  Цитата progman @
                                  все замечательно - но как я узнаю что операция есть?

                                  Ты можешь для отладки сделать счетчики, как Pacific советует?
                                  Цитата progman @
                                  и как я узнаю что она закончена?

                                  Если пришло по ней событие - значит закончена, счетчик уменьшился на 1.

                                  Получается что почти все время жизни объекта счетчик операций в 1 стоит.
                                  Потому как после успешного завершения чтения или посылки данных объект вызывает чтение данных с порта и ждет когда они придут.
                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                  0 пользователей:


                                  Рейтинг@Mail.ru
                                  [ Script execution time: 0,0454 ]   [ 17 queries used ]   [ Generated: 25.04.24, 14:00 GMT ]