Home > Software engineering >  How to wait for a thread created in DLLmain to finish?
How to wait for a thread created in DLLmain to finish?

Time:07-01

I create a new thread in Dllmain() by the CreateThread() API, which does not involve thread synchronization, it is only a separate thread.

Dllmain() invokes WaitForSingleObject(funcThread, INFINITE); to force the main thread to wait for funcThread to finish.

Then I dynamic link this Dllmain(), but the result shows funcThread() finishes early. I know adding a System Pause will work, but do you have some ways to make it work with only changing the Dllmain() file?

What is weird is that it has different results when changing the order of printf() and OutputDebugStringW().

targetFuction.exe

#include <Windows.h>
#include <iostream>

int main() {
    HINSTANCE hModule = LoadLibrary(L"testDllmain.dll");
    return 0;
}

testDllmain.dll

#include <Windows.h>
#include <iostream>

DWORD WINAPI function(LPVOID lpParam) {
    for (int i = 0; i < 100; i  ) {
        printf("%d \n", i);
    }

    return 0;
}
HANDLE funcThread;

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:

        funcThread = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size  
            function,       // thread function name
            NULL,          // argument to thread function 
            0,                      // use default creation flags 
            NULL);
        OutputDebugStringW(L"attach process!\n");

        printf("attach process!\n");

        break;
    case DLL_PROCESS_DETACH:

        WaitForSingleObject(funcThread, INFINITE);
        OutputDebugStringW(L"detach process!\n");
        printf("detach process!\n");
        // printf("detach process!\n");
        // OutputDebugStringW(L"detach process!\n");
        break;
    case DLL_THREAD_ATTACH:
        printf("attach thread!\n");
        OutputDebugStringW(L"attach thread!\n");

        break;

    case DLL_THREAD_DETACH:
        OutputDebugStringW(L"detach thread!\n");

        printf("detach thread!\n");
        break;
    }

    return TRUE;
}

Output:

image

OutputDebugStringW() before printf():

image

printf() before OutputDebugStringW()

image

It should also print 23 to 99 and detach process messages, but all of them are missing.

CodePudding user response:

What you are trying to do is explicitly NOT supported from DllMain().

From Dynamic-Link Library Best Practices:

You should never perform the following tasks from within DllMain:

  • ...
  • Synchronize with other threads. This can cause a deadlock.
  • ...
  • Call ExitThread. Exiting a thread during DLL detach can cause the loader lock to be acquired again, causing a deadlock or a crash.
  • Call CreateThread. Creating a thread can work if you do not synchronize with other threads, but it is risky.

And more.

CodePudding user response:

So, after my questions in comments, and your actions as a response to those comments, what appears to be happening is this:

printf() is not as innocent as it appears to be. It is causing your DLL to freeze when it attempts to print things, probably because it does some kind of synchronization internally.

This may be a consequence of linking the debug multithreaded DLL version of the runtime, or it may be unavoidable no matter how you link the runtime.

You could try to get this thread-spawned-from-DLLmain approach to work without using printf() at all, or you could abandon this approach and come up with an entirely different way of achieving your end-goals, because this approach appears to be a bit too hacky to be viable.

  • Related