Динамическая библиотека и shutdown событие для потока

Тема в разделе "WASM.WIN32", создана пользователем rxznve, 20 авг 2023.

Метки:
  1. rxznve

    rxznve New Member

    Публикаций:
    0
    Регистрация:
    27 фев 2023
    Сообщения:
    14
    Код (C):
    1. HANDLE hShutdownEvent = nullptr;
    2.  
    3. DWORD CALLBACK MainThread(LPVOID lpParameter)
    4. {
    5.     while (WaitForSingleObject(hShutdownEvent, 0) != WAIT_OBJECT_0)
    6.     {
    7.         Sleep(10);
    8.     }
    9.  
    10.     return ERROR_SUCCESS;
    11. }
    12.  
    13. BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD reason, LPVOID lpReserved)
    14. {
    15.     switch (reason)
    16.     {
    17.         case DLL_PROCESS_ATTACH:
    18.         {
    19.             hShutdownEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr);
    20.  
    21.             const HANDLE hMainThread = CreateThread(nullptr, 0, &MainThread, nullptr, 0, nullptr);
    22.  
    23.             if (!hMainThread)
    24.                 return FALSE;
    25.         }
    26.  
    27.         break;
    28.      
    29.         case DLL_PROCESS_DETACH:
    30.             SetEvent(hShutdownEvent);
    31.     }
    32.  
    33.     return TRUE;
    34. }
    При получении библиотекой события DLL_PROCESS_ATTACH вызывается SetEvent который переводит событие hShutdownEvent в сигнальное состояние, однако поток НЕ завершается и процесс падает. В чём дело? Как тогда вообще корректно завершить потоки?
     
  2. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.966
    Старая песня о главном. У DllMain куча ограничений, в ее обработчиках лучше вообще ничего кроме внутренней утилитарщины не делать.
    https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
     
  3. rxznve

    rxznve New Member

    Публикаций:
    0
    Регистрация:
    27 фев 2023
    Сообщения:
    14
    Я думал ограничения распространяются на ожидание, но никак не на SetEvent.
    Как тогда можно дать понять потоку что ему необходимо завершиться?

    Использовать bool переменную не хочется, так как будет сильная нагрузка на процессор.
    WaitForSingleObject внутри потока был идеальным вариантом.
    Даже если вызывать в DLL_PROCESS_DETACH
    Код (C):
    1. PostThreadMessageW(GetThreadId(hMainThread), WM_QUIT, 0, 0);
    И иметь два потока, один главный (с циклом сообщений) а другой с циклом WaitForSingleObject, то все равно происходит краш.
    Что за бред?
    Прикол в том что когда у меня один поток с циклом сообщений и я вызываю из DLL_PROCESS_DETACH

    Код (C):
    1. PostThreadMessageW(GetThreadId(hMainThread), WM_QUIT, 0, 0);
    То он нормально завершается. Но дело в том что мне нужно ДВА потока.
     
  4. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.966
    Общая идея в том, что если тебе надо создавать поток в обработчике события загрузки длл, то ты что-то делаешь неправильно. При обработке импортов например управление туда передается задолго до его передачи в entry point и видимо не всё для этого готово. Законные-легитимные приложения так не строят вобщем.

    ЗЫ: че-то навеяло. TerminateThread попробуй потоком на себя кастовать, мне в похожем случае когда-то помогало.
     
    Последнее редактирование: 20 авг 2023
  5. rxznve

    rxznve New Member

    Публикаций:
    0
    Регистрация:
    27 фев 2023
    Сообщения:
    14
    Я пишу библиотеку-кликер, которая должна иметь возможность быть выгруженной из процесса в любой момент, без завершения целевого процесса. Никаких меню в ней нет, при выгрузке должны завершиться два потока. Дожидаться их завершения не нужно, я лишь хочу чтобы они в итоге просто завершились. TerminateThread работает корректно, но очень мозолит глаза предупреждение о том что очистка потоков не выполнится корректно. Хотелось бы сделать как можно корректно, чтобы на код можно было смотреть без отврата.
     
  6. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.966
    Создавай потоки удаленно. И вообще длл для инжекта в чужой процесс не особо нужна, их используют ради удобства.
     
  7. rxznve

    rxznve New Member

    Публикаций:
    0
    Регистрация:
    27 фев 2023
    Сообщения:
    14
    У меня вроде-бы не с созданием потоков проблема, а с их завершением) Задумка такая, что библиотека это единое целое, нет какого-то приложения которое её внедряет, человек сам должен ее заинжектить чем-то.
    --- Сообщение объединено, 20 авг 2023 ---
    Проблема была в главном потоке библиотеки. Он делал вызов SetEvent и сразу же выгружался, а в моем потоке задержка 10 мс.
    В итоге получалось в итоге что функция WaitForSingleObject обращалась к недоступной памяти и это приводило к крашу.

    Решение нашел не сам, спасибо @DymOk