Корректное завершение потока через TerminateThread

Тема в разделе "WASM.WIN32", создана пользователем vg, 11 июл 2010.

  1. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    Из основного потока вызывается дополнительный
    Код (Text):
    1. hThread DWORD ?
    2. dwCode DWORD ?
    3. ...
    4. invoke CreateThread,0,0,addr ThreadProc,hwin,0,0
    5. mov hThread,eax
    6. invoke GetExitCodeThread,hThread,addr dwCode
    позже при необходимости дополнительный поток принудительно завершается
    Код (Text):
    1. invoke TerminateThread,hThread,dwCode
    В дополнительно потоке вызывается функция из своей dll, где происходит простой перебор и открытие ключей реестра (RegOpenKeyEx, RegEnumKeyEx, ...).
    Проблема в том, что при многократном вызове-завершении дополнительного потока он перестаёт работать (не приходят сообщения на GUI), после закрытия приложения его процесс остаётся висеть в системе. Или при многократном вызове-завершении дополнительного потока приложение виснет.
    В чём может быть причина?

    Вариант с завершение треда через глобальный флаг не устраивает, нужно через TerminateThread.
     
  2. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    vg
    Нельзя потоки прибивать. Это к общей рассинхронизации приведёт, деадлокам, утечкам памяти и пр.
     
  3. onSide

    onSide New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2008
    Сообщения:
    476
    Clerk
    зачем тогда сделали такую возможность? имхо все должно нормально работать, если код потока нормальный.

    Автор, зачем делать GetExitCodeThread сразу после создания потока? Без WaitForSingleObject это не имеет смысла.
    Если остается висеть, так посмотри в каком потоке он висит. На 90% уверен что код бажный, и система тут ни при чем.
     
  4. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    onSide
    Эта функция не для юзания в обычных приложениях. Относится к группе отладочных функций.
    Захватил поток к примеру критическую секцию, вы его прибили - секция останется захваченной, иные потоки будут ждать её освобождения, вот вам и деадлок.)
     
  5. onSide

    onSide New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2008
    Сообщения:
    476
    Clerk
    Понял, согласен.
    Просто я думал что если нормально написать код потока, чтобы в нем ничего не лочилось то будет ок. Но мы ж не знаем как разные апишки работают, и что используют)
     
  6. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    вообще в книжке рихтера помниться было указано достаточно причин, чтобы не прибивать потоки... вообще это сложная тема, одно из самых адекватных решений именно через глобальный флаг, или через ивент... мне однажды пришлось сделать нечто подобное через изменение контекста потока (eip/rip менял на адрес первой инструкции функции освобождения занятых потоком ресурсов и тд, в конце функции стоял ExitThread)... но раз уж нужно убивать поток из другого потока, то придется заботиться о занятых ресурсах... то есть убивать поток, затем освобождать память, всякие там критические секции и тд... и еще рассмотрите функции типа _beginthreadex(), различия между этими CRT функциями и WinAPI опять же есть в рихтере, возможно вам понадобиться использовать именно их...
     
  7. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    Всё ясно. Уже переписываю...
     
  8. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    еще через TerminateThread память из под стека потока не освобождается если много раз прибивать поток через нее все виртуальное пространство процесса будет зарезервировано
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    osox
    Ну конечно. Например proc AllocateHeap() - [...] - FreeHeap(). Вы прибиваете поток не освободивший память. Не понятно вобще что для вас есть "потоки". В NT изоляция задач не имеет смысла. Нельзя рассматривать поток как отдельную независимую от других задачу.
     
  10. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    Clerk
    а вы попробуйте
     
  11. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    osox
    ..
    Ну для меня это задача, а не скриптовое понятие.
     
  12. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    Windows via C/C++
    тест
    Код (Text):
    1. typedef struct
    2. {
    3.     HANDLE hSignal;
    4.     HANDLE hWait;
    5. } THREAD_ARG;
    6.  
    7. void show_avail_address_space(void)
    8. {
    9.     MEMORYSTATUS ms;
    10.     GlobalMemoryStatus(&ms);
    11.     printf("avail address space %lu\n", ms.dwAvailVirtual);
    12. }
    13.  
    14. DWORD WINAPI Ideas(THREAD_ARG *pArg)
    15. {
    16.     SignalObjectAndWait(pArg->hSignal, pArg->hWait, INFINITE, FALSE);
    17.     return 0;
    18. }
    19.  
    20. int main(void)
    21. {
    22.     HANDLE hThread;
    23.     THREAD_ARG Arg;
    24.     Arg.hSignal = CreateEvent(NULL, FALSE, FALSE, NULL);
    25.     Arg.hWait = CreateEvent(NULL, FALSE, FALSE, NULL);
    26.    
    27.     show_avail_address_space();
    28.  
    29.     while (hThread = CreateThread(NULL, 0, Ideas, &Arg, 0, NULL))
    30.     {
    31.         WaitForSingleObject(Arg.hSignal, INFINITE);
    32.         TerminateThread(hThread, ~0);
    33.         CloseHandle(hThread);
    34.     }
    35.  
    36.     show_avail_address_space();
    37.  
    38.     CloseHandle(Arg.hSignal);
    39.     CloseHandle(Arg.hWait);
    40.  
    41.     return 0;
    42. }
    выхлоп
    вся свободная виртуальная память теперь занята
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    osox
    Есть такой обьект как EventPair для таких целей.
    TEB.FreeStackOnTermination(5.1: +0xF75) -> TRUE.
     
  14. K10

    K10 New Member

    Публикаций:
    0
    Регистрация:
    3 окт 2008
    Сообщения:
    1.590
    не продумана структура приложения, поток должен сам завершаться
     
  15. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Когда флажка не было, ExitThread справлялась: можно получить AllocationBase от TEB.StackLimit по средством VirtualQuery и освободить юзер стек самому. Благо со стеком ядра проблем нет.)