How to wait for a thread created in DLLmain to finish?

877 views Asked by At

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.

2

There are 2 answers

2
Pepijn Kramer On

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.

0
YangXiaoPo-MSFT On

According to LoadLibrary, The system unloads a module when its reference count reaches zero or when the process terminates (regardless of the reference count). Then calling FreeLibrary should make main thread execute through DLL_PROCESS_DETACH.
I have tried and then the problem could be the main process is always waiting for the thread but the thread never execute. Is this the risky?

Edit: It should be no problem if the thread function is not in the freed dynamic library.