![]() |
|
Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply |
![]()
|
|
| kami |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 15 Всего: 72 |
В продолжение темы про использование NamedPipes.
По рекомендации dumb вместо пайпов стал использовать MMF. Работа с mmf производится в доп.потоке, данные добавляются асинхронно. Проблема: при аттаче dll в процессы, они подвисают на создании этого доп.потока, обслуживающего mmf. Подвисают на строках в конструкторе:
Ошибка в лог выводится каждый раз одна и та же - 1444, ERROR_INVALID_THREAD_ID. Несмотря на то, что в действительности поток создается и работает нормально (данные от него через mmf приходят исправно). Очередь сообщений доп.потока так же создается и используется:
тестовый пример - во вложении. Где я не прав? Добавлено через 1 минуту и 17 секунд ай-я, пока редактировал - вложение потерялось :( вот оно. Присоединённый файл ( Кол-во скачиваний: 5 )
mmf_hook.rar 8,34 Kb |
||||
|
|||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
на сколько я помню, не рекомендуется делать лишние телодвижения(в т.ч. создавать потоки) в DllMain при загрузке библиотеки...
Добавлено через 9 минут и 52 секунды хотя нет, я не прав - явного запрета на создание потока в DllMain я не нашел... но... может стоит крайне упростить код, выполняемый в ней. не очень хорошо пускать цикл, начинать писать в файл, чего-то ждать, имхо. -------------------- There are always someone smarter than you... |
|||
|
||||
| kami |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 15 Всего: 72 |
точно, нашел такое... DllMain callback function, в ремарках. Если точнее, то
А як жеш быть? imho, лучше 1 раз потерять во времени при инициализации, чем каждый раз на вызове хука для синхронизации обращения к разделяемому ресурсу... Это сообщение отредактировал(а) kami - 17.5.2009, 16:23 |
||||
|
|||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
кстати, а как вообще написана DllMain?
-------------------- There are always someone smarter than you... |
|||
|
||||
| kami |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 15 Всего: 72 |
В файл пишется только для отладки, в готовом коде это будет убрано. Цикл в конструкторе доп.потока могу убрать, но тогда нет уверенности в том, что при обращении к его методам он будет уже проинициализирован. Сейчас пришла мысль: А если инициализацию провести при первом вызове процедуры хука? Правда, это тоже не рекомендуется - инициализация процесс длительный, Windows может не дождаться его окончания и прервать выполнение hook callback функции... Добавлено через 3 минуты и 52 секунды
|
||||
|
|||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
расшифруй плиз... в общем тут дело такое - создать то поток можно, но нельзя в него "лезть" из dllmain. а инициализировать можно все в Execute потока. ибо, как написано у Рихтера, все DllMain вызываются линейно. и у тебя как раз такая ситуация, что поток не будет запущен, пока не отработает DllMain c DLL_THREAD_ATTACH, а она не запустится, пока не отработает DLLMain с DLL_PROCESS_ATTACH -------------------- There are always someone smarter than you... |
|||
|
||||
| kami |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 15 Всего: 72 |
Хук пишет данные в mmf, основная программа "выгребает" их. Чтобы не было накладок (один недописал, второй уже считал и обнулил mmf) идет синхронизация с помощью мьютексов. Если добавлять данные в mmf непосредственно из потока, в котором вызыван хук, то неизвестно, сколько времени будет потеряно на WaitFor-ожидание, что для хука недопустимо. Посему было сделано так - данные из хука в доп.поток, работающий с mmf, передаются с помощью PostThreadMessage, что не задерживает выполнение хука. А этот доп.поток пускай ждет сколько угодно - его ожидания не лимитируют. Это и имел ввиду, говоря "лучше день потерять, зато потом за 5 минут долететь" Ух ты... спасибо, буду знать. |
|||
|
||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
kami, а какой смысл в конструкторе потока слать PostThreadMessage? чтобы убедиться, что создалась очередь сообщений потока?неужели это настолько критично?
-------------------- There are always someone smarter than you... |
|||
|
||||
| kami |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 15 Всего: 72 |
В условиях данной задачи (имеется ввиду - полной задачи, а не этого упрощения) - некритично. Но я не люблю что-то сделав, возвращаться потом к тому же вопросу для доработки. (например, в разрабатываемом классе есть ф-и AddData, GetAllData, но нет GetFirstData). Вдруг в другой задаче нужно будет отправить критически важные данные сразу после создания MMFThread? Предпочитаю делать что-либо с претензией на какую-никакую, а универсальность |
|||
|
||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
кстати... к алгоритму можно придраться... имхо - он не надежен.
ибо Post{Thread}Message не гарантирует доставку сообщения. а ты наверняка передаешь с пом.него данные, которые затем будут очищаться в потоке? а если потоку сказали Terminate, он завершится не обработав возможно ожидающие в очереди сообщения... в общем мое мнение: сообщения можно здесь использовать только для нотификации, но никак не для передачи важных данных. Добавлено через 11 секунд з.ы. конечно же я могу быть не прав -------------------- There are always someone smarter than you... |
|||
|
||||
| CodeMonkey |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 16 Всего: 89 |
Подробное описание проблем с DllMain (серия на 4 поста).
Далее, из ERROR_INVALID_THREAD_ID - двойку вам за знание TThread. Поток запускается ТОЛЬКО после выхода из конструктора (в AfterConstruction). Хитроумные манипуляции с Resume здесь не к месту. Вставьте этот код на Execute. Даже, если вы оставите подобный подход - нет гарантии, что поток успеет создастся до вызова PostThreadMessage - вам всё равно нужна доп. синхронизация. И ещё MetalFan прав насчёт возмодности пропуска сообщений. Для синхронизации потоков надо использовать события, крит. секции и др. объекты. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
| kami |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 15 Всего: 72 |
Совершенно верно. PostMessage(msgAddData, integer(pData), DataSize);
Поток будет терминирован, если: 1. Завершено приложение, в которое внедрен хук. 2. Вызывано UnHookWindowsHookEx для всех установленных из dll хуков. И в том и в другом случае приходящие после этого данные уже не актуальны. |
||||
|
|||||
| kami |
|
||||||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 15 Всего: 72 |
Протестую!
А AfterConstruction только и делает, что вызывает Resume при необходимости. Я же вызывал его в явном виде в своем классе после inherited Create(True). Просветите меня, если это ошибочно. В Execute выполняется код, предназначенный к выполнению в доп.потоке, инициализация данных и ожидание начала работы потока должны происходить не в нем.
Как раз-таки этот цикл гарантирует, что: 1. поток запущен и вошел в Execute. 2. Очередь сообщений инициализирована и работает. Добавлено через 4 минуты и 52 секунды
Тем самым стопоря работу осн.потока. Самым простым методом синхронизации будет создание окна в доп.потоке и передача данных в него с помощью SendMessage, что гарантирует поступление данных в поток до выхода из оконной процедуры, т.е. до выхода из SendMessage. Такая возможность заложена, в примере (вложение первого поста) реализована. Добавлено через 11 минут и 44 секунды Уже понял из msdn. Кошмар! dll придется пересматривать :( Это сообщение отредактировал(а) kami - 17.5.2009, 22:14 |
||||||||
|
|||||||||
| MetalFan |
|
||||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
ну уж извините) и рыбку съесть и.... не получится. либо синхронизация либо возможная порча данных. а синхронизация с пом. SendMessage конечно проста, но имхо не самый быстрый и надежный вариант. Это сообщение отредактировал(а) MetalFan - 18.5.2009, 12:40 -------------------- There are always someone smarter than you... |
||||
|
|||||
| CodeMonkey |
|
||||||||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 16 Всего: 89 |
Нет, почему же: MsgWaitForMultipleObjects (см. также TThread.WaitFor). Да даже, если просто тупо WaitForSingleObject - там "завис"-то будет в сотые доли секунды. И уж всяко меньше вашего Sleep(100). Что, долго потоку раскручиваться, что-ли?
А о том, что Resume в AfterConstruction вызывается - вы не подумали? Такие действия надо делать так:
Да, что-то я не так этот код прочитал Тогда проверяйте свой код - должен работать. Может, конечно, первая итерация и с ERROR_INVALID_THREAD_ID будет, но вторая - успешно. Что-то мне кажется, вы с i напутали. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
||||||||||
|
|||||||||||
![]()
|
| Правила форума "Delphi: WinAPI и системное программирование" | |
|
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |