Buddhi Chaturanga Ответов: 1

Безопасно ли вызывать функцию std:: thread:: join в win32 DLL_PROCESS_DETACH?


Пожалуйста, посмотрите на фрагмент кода ниже / / эти блоки кода, определенные в разделе single .СРР блок в файл DLL проект
------------------ файл DLL -------------------------

static std::thread sendMessageThread; // define as local static to cpp
//....//
bool  callFunction()
{
   /// Some simple code without spawning any thread or fibers
 }
void WINAPI OnEngineStart()
{
    sendMessageThread = std::thread(callFunction);
};

    BOOL WINAPI DllMain(HINSTANCE hDll, DWORD fdwReason, LPVOID lpvReserved)
    {
        switch (fdwReason)
        {
        case DLL_PROCESS_ATTACH:
            break;
        case DLL_PROCESS_DETACH:
            if (sendMessageThread.joinable())
            {
                sendMessageThread.join(); // is this safe?
            }
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
        }

    return TRUE;
};


------------------------------------- файл DLL --------------------------

Если процесс, который загрузил DLL, вызывает функцию OnEngineStart, то всякий раз, когда он выгружает DLL(используя функцию FreeLibrary WinAPI), будет ли он ждать, пока sendMessageThread не будет завершен? и продолжить процедуру выгрузки DLL?

Что я уже пробовал:

Я запускаю программу с этой DLL-библиотекой, программа никогда не падает и не останавливается.Но я нашел эти вещи:
Создает ли создание потока из DllMain тупик или нет? - Старая Новая Штука[^]
Рекомендации По Использованию Библиотеки Динамических Ссылок (Windows)[^]

1 Ответов

Рейтинг:
1

Randor

Нет- вы делаете именно то, что Рэймонд Чен описывает в своей записи в блоге. Вы ждете потока в вашем DLL_PROCESS_DETACH. Убедитесь, что вы понимаете, что "Уведомления DLL сериализуются" означает.

Я думаю, что знаю способ продемонстрировать, почему это плохая идея... добавьте какой-нибудь код в свой sendMessageThread, который вызывает в разделе getenv_s, _wgetenv_s[^]. Также добавьте некоторый код в ваш родительский процесс, чтобы периодически загружать / выгружать DLL. Это в конечном итоге должно привести к тому, что ваш код будет заблокирован. Причина тупика заключается в том, что CRT обращается к глобальному _ENV_LOCK и потенциально может вызвать состояние гонки. Есть десятки других сценариев, которые приведут к тупику.

Одно из возможных решений состоит в том, чтобы изменить свою архитектуру, добавив сообщение потока OnEngineStop и сделать свое ожидание там.

с наилучшими пожеланиями,
- Дэвид Делон