4
votes

I'm writing a DLL that needs to call a separate DLL dynamically multiple times. I would like to keep the callee loaded and then just unload it when my DLL is unloaded. But according to Microsoft, that's a bad idea.

The entry point function should only perform simple initialization tasks and should not call any other DLL loading or termination functions. For example, in the entry point function, you should not directly or indirectly call the LoadLibrary function or the LoadLibraryEx function. Additionally, you should not call the FreeLibrary function when the process is terminating.

Here's the offending code. Can somebody explain why I shouldn't call LoadLibrary and FreeLibrary from my DLL's entry point?

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
switch (ul_reason_for_call) {
    case DLL_PROCESS_DETACH :
            if (hLogLib != NULL) FreeLibrary(hLogLib);
            break;
    }
    return TRUE;
}
3
How do you know that the DLL hasn't been unloaded already? - Anon.
@Anon: I don't. In fact, I don't know that it was ever even loaded. But if it was loaded and hasn't already been unloaded, I want to unload it. - John M Gant
Sounds like you should be static-linking to the other DLL, rather than trying to dynamically load it. - Remy Lebeau
@Remy, I would if I could. The path to the DLL isn't available at compile time. - John M Gant
Perhaps the stress is on the part "you should not call the FreeLibrary function when the process is terminating." That is, when the process is terminating then do not do anything, maybe the goal is to just quit as soon as possible in order to conserve computing resources. - Roland Pihlakas

3 Answers

4
votes

I think I've found the answer.

The entry-point function should perform only simple initialization or termination tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions), because this may create dependency loops in the DLL load order. This can result in a DLL being used before the system has executed its initialization code. Similarly, the entry-point function must not call the FreeLibrary function (or a function that calls FreeLibrary) during process termination, because this can result in a DLL being used after the system has executed its termination code.

2
votes

You can't call LoadLibrary from your entry point because the DllMain function runs inside an OS loader lock and any attempts to reacquire that loader lock (for instance, by calling LoadLibrary) will result in deadlock.

2
votes

Don't do anything of consequence inside of DLLMain. Seriously. Calling FreeLibrary is even worse because it'll only sometimes deadlock, if it happens that your free decrements the refcount to zero and the library is actually freed.