Search code examples
windowsvisual-c++dllloadlibrarydllmain

Safe place to put unsafe DLL cleanup code on Windows?


We hit a case where it would be the best solution for us to put a FreeLibrary call into DllMain / DLL_PROCESS_DETACH.

Of course, you must not do that:

It is not safe to call FreeLibrary from DllMain.

The use case is that we have a situation like this:

(unknown client dll or exe) links dynamically or statically to -> 
      -> DLL_1, loads dynamically -> DLL_x

DLL_1 should load DLL_x transparently wrt. to it's client code, and it should to load DLL_x dynamically. Now, the loading can be done lazily, so that the LoadLibrary call needn't reside in the DLL_PROCESS_ATTACH part of DLL_1.

But once the client is done with DLL_1, when/before DLL_1 is unloaded from the process, it should also unload (== FreeLibrary) DLL_x.

Is there any way to do this without an explicit DLL_1/Uninitialize function that must be called by the client?

I'll note:

  • DllMain, and thus also any C++ global static destructor cannot be used.
  • Is there any other callback mechanism in either kernel32/ntdll or maybe in the shared MS CRT to make this happen?
  • Are there other patterns to make this usecase work?

Solution

  • The correct approach is an explicit Uninitialize function in DLL_1.

    However, if you can't do that, you can work around the problem by launching a helper thread to do the unload for you. If you want to play it safe, launch the thread at the same time you load DLL_x and have it wait on an event object. (For the record, though, it is generally considered safe to launch a thread from DllMain so long as you respect the fact that it won't start up until DllMain has exited.)

    Obviously, the helper thread's code can't be in DLL_1. If you can modify DLL_x you can put it there. If not, you'll need a helper DLL. In either case, the DLL containing the helper thread's code can safely self-unload using the FreeLibraryAndExitThread function.