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 08月04日
- 实战经验:时刻关注类对象内部数据成员状态
- Posted on 10月22日
- 技法:对你的应用添加键盘加速键
- Posted on 06月20日
- VS2022 性能提升:更快的 C++ 代码索引
- Posted on 11月16日
评论已关闭。