DllMain中可能出现的意外死锁
潜在的死锁
DllMain函数执行的时候,Windows会为它创建一个独占的环境(锁),这是操作系统在使用它内部的锁机制的几种比较少见的情况之一。这也意味着,你必须十分小心那些导致DllMain函数中可能出现的死锁情况发生。
举个例子
加载器锁可以被任意需要访问加载到进程中的DLL列表的函数获取到,这其中包括像GetModuleHandle和GetModuleFileName之类的函数。如果你的DllMain进入了一个临界区或者等待一个同步对象,同时,这个临界区或同步对象又被另一段代码所持有,这些代码又等待加载器锁,则这种情况下就会产生一个死锁,我们看看下面的例子:

现在想象一下,某个线程正在愉快地执行第一个代码片段并进入临界区g_csGlobal,然后它的执行时间片被操作系统所抢占。在这段时间内,另一个线程退出。 这将进入加载器锁并在仍然保持加载程序锁的同时发送DLL_THREAD_DETACH通知。
你将会收到DLL_THREAD_DETACH通知,并尝试进入DLL中的临界区g_csGlobal。这将会导致代码在拥有临界区的第一个线程上阻塞。然后,该线程恢复执行并调用GetModuleFileName,此函数调用需要加载器锁(因为它正在访问已加载到进程中的DLL列表),因此此函数将被阻塞,因为加载器锁由其他代码所持有。
这个时候,就会出现一个死锁。
> g_cs被第一个线程所持有,并等待加载器锁。
> 加载器锁被第二个线程所持有,并等待g_cs。
总结
本文所要讲述的故事:请认真对待操作系统的加载器锁。如果你在DllMain中进行任何锁定的操作,请将它规划在锁层次结构规则中。
最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Another reason not to do anything scary in your DllMain: Inadvertent deadlock》
- 下一篇: 一个潜在问题:内存分配操作中可能出现的整数溢出
- 上一篇: 记得,不要在DllMain中做很复杂的操作
相关推荐
- 系统设计之道:将取消作为对话框的默认按钮
- Posted on 03月11日
- 滚动条系列:第11章答案
- Posted on 04月29日
- 第 119 期:Windows 11 KB5062553 24H2 大更新
- Posted on 07月09日
- 说说RegisterClass这个函数返回值的作用
- Posted on 11月22日



评论已关闭。