![]() |
Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply |
![]() ![]() ![]() |
|
Dota |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 12.7.2008 Репутация: нет Всего: нет |
Почему поток обрывается при закрытии главного окна и завершается приложение?
Блин, где не читаю, везде пишут, что процесс завершится только тогда, когда завершится последний поток. А тут получается что то принудительно его завершает. Ситуация усложняется еще и тем, что потоки собираюсь создавать в DLL и программа, которая будет использовать DLL точно также может в любой момент обрываться и обрывается поток...
Это сообщение отредактировал(а) Dota - 24.7.2010, 21:10 |
|||
|
||||
CodeMonkey |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 16 Всего: 89 |
Потому что "end." в dpr файле - это вызов Halt(0).
-------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
xkor |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 51 Регистрация: 8.1.2007 Где: Питер Репутация: нет Всего: 4 |
CodeMonkey, и это надо сказать вполне логично учитывая что на "end." ещё и finalization у всех модулей вызывается
Dota, прими как данность что в обычном дельфи-приложении основной поток должен умирать последним При завершении программы вроде должна вызываться основная функция длл (DllProc вроде обзывается в дельфи и её ещё надо обозначить иначе стандартная заглушка только finalization модулей вызовет, хотя можно и через них) с параметром что длл выгружается, вот в этот момент можно послать всем своим потокам сигнал что надо срочно завершаться и дождаться их завершения Хотя не уверен что эта функция вызывается если программа завершается по Halt |
|||
|
||||
Dota |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 12.7.2008 Репутация: нет Всего: нет |
Спасибо. Теперь ясно, что не кошерно все устроено в этом плане.
|
|||
|
||||
CodeMonkey |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 16 Всего: 89 |
Пффф. Будьте осторожны: ваши желания могут исполнится. И тогда вам это не понравится. Подумайте сами почему. xkor уже дал подсказку.
И с неслабым шансом получим deadlock, потому что завершение потока приводит к вызову DllMain, которая блокирована главным потоком. Потоки должны закрыться до того, как DLL начнёт процесс выгрузки. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
xkor |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 51 Регистрация: 8.1.2007 Где: Питер Репутация: нет Всего: 4 |
блин точно, как то не подумал об этом...
и как тогда потоки должны узнавать о том что процессу вот вот настанет конец? |
||||
|
|||||
CodeMonkey |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 16 Всего: 89 |
Очевидно, что протокол DLL должен предусматривать функцию Done (и Init). Часто народ думает: во, у нас же есть DllMain! Давайте сюда поместим инициализацию и очистку ресурсов (в нашем случае: остановку потоков). Но они не осознают, что DllMain - это особое место. К примеру, пакеты Delphi так и устроены: несмотря на то, что это просто DLL, их инициализация и финализация выброшены в отдельные функции, а не выполняется в рамках DllMain. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
Dota |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 12.7.2008 Репутация: нет Всего: нет |
Я пока придумал решение - использовать критические секции в DLLMain. Поток в начале работы входит в критическую секцию. И DLLMain тоже входит. Пока поток не покинет критическую секцию DLLMain будет ждать...
|
|||
|
||||
CodeMonkey |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 16 Всего: 89 |
Поздравляю, ваши шансы на deadlock только что удвоились. Если раньше у вас была только блокировка загрузчика, то теперь у вас есть ещё и критическая секция. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
Dota |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 12.7.2008 Репутация: нет Всего: нет |
Но ведь критическая секция работает, если верить Рихтеру на пользовательском уровне, оперируя атомарными операциями...
Есть ли способ доработать потоку правильными методами? |
|||
|
||||
CodeMonkey |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 16 Всего: 89 |
А причём тут это? Что, по-вашему произойдёт, если один поток войдёт в критическую секцию (или в любой другой объект синхронизации) и будет ждать там другой поток, которому тоже нужно туда войти? Deadlock и получится. Вы, кажется, не поняли, о чём идёт речь. Попробуйте вдумчиво прочитать того же Рихтера, где он говорит про DllMain, или эту серию из четырёх постов. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
Dota |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 12.7.2008 Репутация: нет Всего: нет |
Никак не могу прикинуть, где деадлок может случиться.
Имеем 2 и более теоретически возможно возникающих потока в DLL. Запускаются потоки. Входим в критическую секцию. Внезапно завершается приложение, вызывается DLLMain с параметром DLL_PROCESS_DETACH. Входим в эту же критическую секцию. Ждем пока нам не отдадут управление над критической секцией. Завершаем DLLMain _не выходя из критической секции_, тоесть все потоки которые не начали работу, ожидая своей очереди, автоматически умрут с приложением. |
|||
|
||||
Dota |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 12.7.2008 Репутация: нет Всего: нет |
Попробывал использовать критическую секцию в DLLMain - фиг там, не пашет, сразу пропускает.
Хотя сколько коду видел и сколько валяется на теренах интернета, где пользуются критическими секциями в DLLMain ничего не подозревая. Даже в официальных примерах MSDN, если память не изменяет! |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 21 Всего: 88 |
-------------------- Обижено школьников: 8 |
|||
|
||||
Dota |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 12.7.2008 Репутация: нет Всего: нет |
Вообщем ситуация такая. ExitProcess используемый всеми программами для корректного завершения убивает все остальные потоки, кроме того, с которого вызван ExitProcess еще до того, как вызывается DLLMain PROCESS_DETACH
![]() Единственное решение, еще написанное Рихтером - секас с перехватом ExitProcess. Это сообщение отредактировал(а) Dota - 29.7.2010, 10:57 |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: WinAPI и системное программирование" | |
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |