【问题标题】:Exit thread upon deleting static object during unload DLL causes deadlock?在卸载 DLL 期间删除静态对象时退出线程导致死锁?
【发布时间】:2012-05-04 00:11:42
【问题描述】:

我的延迟加载 DLL 中有一个实例(全局/静态对象)ClassA。这个对象里面有一个“观察者”线程,它是执行正常关闭所必需的。当我调用 FreeLibrary 时,我注意到在删除此静态对象期间,我的线程请求关闭,但挂在 _endthreadex() 上并导致死锁。我是显式还是隐式调用 _endthreadex 都没有关系。对象是全局的还是静态的都没关系——结果相同。 该线程包裹在 ClassB 中(由带有自定义消息循环的模板实现)。有一个关闭线程的请求(发布消息)并跟随 WaitForSingleObject,它永远不会返回给定的线程句柄。

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

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

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

【问题讨论】:

  • 不要在您的DllMain 中使用anything scary。全局对象在 DllMain 中构造/销毁。
  • 来自 DllMAin 的文档 - 因为 DLL 通知是序列化的,所以入口点函数不应尝试与其他线程或进程通信。结果可能会发生死锁。 通常,在 DLL 终止期间您不能做很多事情。
  • 死锁往往很容易诊断,您可以花时间使用 Debug + Break All 闯入调试器。查看线程的堆栈跟踪可以提供重要的线索。请务必启用调试符号服务器。
  • @dave 谢谢。这就解释了我得到了什么......

标签: c++ windows multithreading deadlock


【解决方案1】:

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

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

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

【讨论】:

  • 谢谢。这正是我所做的。我踢掉了所有单例/静态对象并将它们变成了常规类。然后在 InitializeLibrary() 中初始化单个接口指针以访问这些类的实例。
  • 非常感谢您的解释。我曾经并且仍然有这个麻烦,现在它是有道理的。我也很生气,因为我自己没有弄清楚,因为我看到它如此接近。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-18
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多