我在看一个挂在Server 2016上但运行在服务器2008 R2上的应用程序。我将其追溯到在加载特定DLL时由死锁引起的挂起。分析DLL (我没有源代码)我可以看到它违反了这里准则
具体来说,它从GetStringTypeW调用DllMain。
我试图了解这个函数如何在DllMain中造成死锁。
发布于 2020-02-20 04:19:07
您的DllMain函数在加载程序锁中运行,这是操作系统允许您在其内部锁持有时运行代码的少数几次之一。这意味着您必须格外小心,不要违反您的DllMain中的锁层次结构;否则,您将请求死锁。(参见"在DllMain中不做任何可怕事情的另一个原因是:不经意的死锁")
在加载程序锁保持时调用DllMain,因此如果GetStringType获得加载程序锁,则会出现死锁。
对可以在DllMain中调用的函数施加了重要的限制。因此,DllMain被设计为通过使用Microsoft的一个小子集来执行最小的初始化任务。您不能在DllMain中调用任何直接或间接尝试获取加载程序锁的函数。否则,您将引入应用程序死锁或崩溃的可能性。
我们看不到GetStringType函数的源代码。建议采用动态链接库最佳实践。
发布于 2020-02-20 12:23:30
从DllMain调用将(直接或间接)加载另一个模块的函数将陷入死锁。
模块加载是序列化的。系统使用锁确保在任何给定时间输入的DLL入口点不超过一个。如果从DLL入口点(直接或间接)调用LoadLibrary,则持有加载程序锁。LoadLibrary将在调用模块的入口点之前尝试获取加载程序锁本身。因此,当您的代码等待LoadLibrary返回时,LoadLibrary正在等待您所持有的锁。这是个僵局。
这很可能是从GetStringType死锁调用DllMain的原因。但是,如果没有对源代码的访问,我就无法验证这一点。您可以通过启用装载机抢断来找到证据。
https://stackoverflow.com/questions/60312037
复制相似问题