I have one instance (global/static object) ClassA inside of my delay-loaded DLL. This object inside has an "Observer" thread which is required to perform graceful shutdown. When I call FreeLibrary I noticed that during deletion of this static object my thread requested to shutdown but hangs on _endthreadex() and causes deadlock. It doesn't matter if I call _endthreadex explicitly or implicitly. It doesn't matter if object is global or static - same result. This thread wrapped in ClassB (implemented by template with custom message loop). There is a request to shutdown thread (post message) and following WaitForSingleObject which never returns for given thread heandle.
Same "template thread class" used everywhere in the code and shutdown works great. The only issue when deleting static obj. I think there is some lock inside of _endthreadex() which is already locked upon dll unload and deleting of static objects.
Thread started with _beginthreadex. ps. When I instantiated same static obj inside of App - app closes without any significant issues.
Any ideas why _endtreadex causes deadlock? How to avoid it?
This particular case is easy to explain. The _endthreadex call needs the loader lock so that it can call DllMain with DLL_THREAD_DETACH. The thread that called FreeLibrary, however, already holds the loader lock, because you're already in the middle of a call to DllMain with DLL_PROCESS_DETACH.
The other way this can break is that if the process exits without explicitly unloading the library, your observer thread will be terminated before the DLL_PROCESS_DETACH call, so when you try to signal it to exit, it won't respond because it isn't running any more.
The best approach is probably to create explicit InitializeLibrary() and UninitializeLibrary() functions for the user to call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With