0

Please look at code snippet below // these code blocks defined under single .cpp unit in DLL project

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;
};

If the process which loaded the DLL call OnEngineStart function then whenever it unloads the DLL(using FreeLibrary WinAPI function), will it wait until sendMessageThread gets finished? and continue with DLL unload procedure?

  • yes. this is deadlock:1. you wait on thread terminated and only after this release loader lock 2. thread wait when you release loader lock and only after this terminated 3. deadlock – RbMm Sep 26 '17 at 11:47
  • 1
    and you need not wait for thread in dll but increment reference count for this dll, before thread start. say via `GetModuleHandleEx`. and on exit thread by call `FreeLibraryAndExitThread` – RbMm Sep 26 '17 at 12:04
  • @RbMm you told "yes" meant -> it is safe? since the std::thread doesn't invoke within DLLMain.. unless it will be deadlock? or still std::thread::join() affect DLL_THREAD_DETACH and then DLL_PROCESS_DETACH? –  Sep 26 '17 at 13:55
  • i say that this will be deadlock. and explain why. *yes* was related to previous comment, already deleted – RbMm Sep 26 '17 at 13:58
  • `std::thread::join() ` wait inside critical section until thread exit. but thread before exit try enter to this critical section for send `DLL_THREAD_DETACH`. if you create thread with entry point in dll - you must call `GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, &__ImageBase, )` before create thread. and exit thread by call `FreeLibraryAndExitThread` - in this case you need not wait in `DLL_PROCESS_DETACH` – RbMm Sep 26 '17 at 14:02
  • [Does creating a thread from DllMain deadlock or doesn’t it?](https://blogs.msdn.microsoft.com/oldnewthing/20070904-00/?p=25283) – IInspectable Sep 26 '17 at 14:23
  • @RbMm my program didn't crash or halt –  Sep 26 '17 at 14:59
  • @IInspectable here std::thread wasn't create in DLLMain –  Sep 26 '17 at 15:00
  • Why does that make a difference? The article I linked to explains what happens, when you try to wait for the thread to terminate in your `DLL_PROCESS_DETACH` handler. This is a guaranteed deadlock. – IInspectable Sep 26 '17 at 15:01
  • @IInspectable so when/where can I invoke std::thread::join() function? Should I set semaphore or event under DLL_THREAD_DETACH and upon that signal stop the running thread ? ... If thread stopped before the DLL_PROCESS_DETACH invoke join function safe right? –  Sep 26 '17 at 15:16
  • *my program didn't crash or halt* about crash nobody say. if it not deadlock when wait in loader lock for thread exit - this mean that this tread already exited. in this case of course no deadlock. – RbMm Sep 26 '17 at 15:25
  • @RbMm, [according to this](https://stackoverflow.com/a/36914735/886887) on older versions of Visual Studio the `std::thread` class uses the concurrency runtime. It seems to me that this *might* mean that when a C++ thread exits, the corresponding Windows thread is returned to a pool rather than exiting immediately. **If** my guess is correct, then in older versions of Visual Studio calling `.join()` doesn't wait for the Windows thread and therefore won't necessarily deadlock. It *is* just a guess though. – Harry Johnston Sep 26 '17 at 21:03
  • 1
    ... of course, even if that's true, the answer is still the same: no, the code in question isn't safe, because (a) it depends on an implementation detail that has already changed, and (b) you might still run into trouble if the executable isn't sharing the same runtime as the DLL. – Harry Johnston Sep 26 '17 at 21:05

0 Answers0