在卸载 DLL 期间删除静态对象时退出线程会导致死锁

Exit thread upon deleting static object during unload DLL causes deadlock?

本文关键字:线程 退出 死锁 对象 DLL 卸载 静态 删除      更新时间:2023-10-16

我在延迟加载的 DLL 中有一个实例(全局/静态对象(ClassA。这个对象里面有一个"观察者"线程,这是执行正常关闭所必需的。当我调用 FreeLibrary 时,我注意到在删除此静态对象期间,我的线程请求关闭,但挂起在 _endthreadex(( 上并导致死锁。我是否显式或隐式地调用_endthreadex并不重要。对象是全局的还是静态的并不重要 - 相同的结果。此线程包装在 ClassB 中(由具有自定义消息循环的模板实现(。有一个关闭线程(发布消息(的请求,并遵循 WaitForSingleObject,它永远不会返回给定的线程 heandle。

在代码和关闭中随处使用相同的"模板线程类"效果很好。删除静态对象时的唯一问题。我认为 _endthreadex(( 内部有一些锁,它已经在 dll 卸载和删除静态对象时被锁定。

线程从_beginthreadex开始。当我在应用程序内实例化相同的静态 obj 时 - 应用程序关闭没有任何重大问题。

知道为什么_endtreadex会导致死锁吗?如何避免?

这种特殊情况很容易解释。 _endthreadex调用需要加载程序锁,以便它可以调用 DllMain DLL_THREAD_DETACH。 但是,调用 FreeLibrary 的线程已经持有加载程序锁,因为您已经在使用 DLL_PROCESS_DETACH 调用 DllMain 的过程中。

另一种可能中断的方式是,如果进程在没有显式卸载库的情况下退出,则观察器线程将在DLL_PROCESS_DETACH调用之前终止,因此当您尝试向其发出退出信号时,它不会响应,因为它不再运行。

最好的方法可能是创建显式的 InitializeLibrary(( 和 UninitializeLibrary(( 函数供用户调用。