Из основного потока вызывается дополнительный Код (Text): hThread DWORD ? dwCode DWORD ? ... invoke CreateThread,0,0,addr ThreadProc,hwin,0,0 mov hThread,eax invoke GetExitCodeThread,hThread,addr dwCode позже при необходимости дополнительный поток принудительно завершается Код (Text): invoke TerminateThread,hThread,dwCode В дополнительно потоке вызывается функция из своей dll, где происходит простой перебор и открытие ключей реестра (RegOpenKeyEx, RegEnumKeyEx, ...). Проблема в том, что при многократном вызове-завершении дополнительного потока он перестаёт работать (не приходят сообщения на GUI), после закрытия приложения его процесс остаётся висеть в системе. Или при многократном вызове-завершении дополнительного потока приложение виснет. В чём может быть причина? Вариант с завершение треда через глобальный флаг не устраивает, нужно через TerminateThread.
Clerk зачем тогда сделали такую возможность? имхо все должно нормально работать, если код потока нормальный. Автор, зачем делать GetExitCodeThread сразу после создания потока? Без WaitForSingleObject это не имеет смысла. Если остается висеть, так посмотри в каком потоке он висит. На 90% уверен что код бажный, и система тут ни при чем.
onSide Эта функция не для юзания в обычных приложениях. Относится к группе отладочных функций. Захватил поток к примеру критическую секцию, вы его прибили - секция останется захваченной, иные потоки будут ждать её освобождения, вот вам и деадлок.)
Clerk Понял, согласен. Просто я думал что если нормально написать код потока, чтобы в нем ничего не лочилось то будет ок. Но мы ж не знаем как разные апишки работают, и что используют)
вообще в книжке рихтера помниться было указано достаточно причин, чтобы не прибивать потоки... вообще это сложная тема, одно из самых адекватных решений именно через глобальный флаг, или через ивент... мне однажды пришлось сделать нечто подобное через изменение контекста потока (eip/rip менял на адрес первой инструкции функции освобождения занятых потоком ресурсов и тд, в конце функции стоял ExitThread)... но раз уж нужно убивать поток из другого потока, то придется заботиться о занятых ресурсах... то есть убивать поток, затем освобождать память, всякие там критические секции и тд... и еще рассмотрите функции типа _beginthreadex(), различия между этими CRT функциями и WinAPI опять же есть в рихтере, возможно вам понадобиться использовать именно их...
еще через TerminateThread память из под стека потока не освобождается если много раз прибивать поток через нее все виртуальное пространство процесса будет зарезервировано
osox Ну конечно. Например proc AllocateHeap() - [...] - FreeHeap(). Вы прибиваете поток не освободивший память. Не понятно вобще что для вас есть "потоки". В NT изоляция задач не имеет смысла. Нельзя рассматривать поток как отдельную независимую от других задачу.
Windows via C/C++ тест Код (Text): typedef struct { HANDLE hSignal; HANDLE hWait; } THREAD_ARG; void show_avail_address_space(void) { MEMORYSTATUS ms; GlobalMemoryStatus(&ms); printf("avail address space %lu\n", ms.dwAvailVirtual); } DWORD WINAPI Ideas(THREAD_ARG *pArg) { SignalObjectAndWait(pArg->hSignal, pArg->hWait, INFINITE, FALSE); return 0; } int main(void) { HANDLE hThread; THREAD_ARG Arg; Arg.hSignal = CreateEvent(NULL, FALSE, FALSE, NULL); Arg.hWait = CreateEvent(NULL, FALSE, FALSE, NULL); show_avail_address_space(); while (hThread = CreateThread(NULL, 0, Ideas, &Arg, 0, NULL)) { WaitForSingleObject(Arg.hSignal, INFINITE); TerminateThread(hThread, ~0); CloseHandle(hThread); } show_avail_address_space(); CloseHandle(Arg.hSignal); CloseHandle(Arg.hWait); return 0; } выхлоп вся свободная виртуальная память теперь занята
osox Есть такой обьект как EventPair для таких целей. TEB.FreeStackOnTermination(5.1: +0xF75) -> TRUE.
Когда флажка не было, ExitThread справлялась: можно получить AllocationBase от TEB.StackLimit по средством VirtualQuery и освободить юзер стек самому. Благо со стеком ядра проблем нет.)