之前几篇文章主要介绍和分析了为什么会在DllMain做出一些不当操作导致死锁的原因。本文将总结以前文章的结论,并介绍些DllMain中还有哪些操作会导致死锁等问题。(
转载请指明出于breaksoftware的csdn博客)
DllMain的相关特性 首先列出《DllMain中不当操作导致死锁问题的分析--进程对DllMain函数的调用规律的研究和分析》中论证的11个特性:
-
Dll的加载不会导致之前创建的线程调用其DllMain函数。
- 线程创建后会调用已经加载了的DLL的DllMain,且调用原因是DLL_THREAD_ATTACH。(DisableThreadLibraryCalls会导致该过程不被调用)
- TerminateThread方式终止线程是不会让该线程去调用该进程中加载的Dll的DllMain。
- 线程正常退出时,会调用进程中还没卸载的DLL的DllMain,且调用原因是DLL_THREAD_DETACH。
- 进程正常退出时,会调用(不一定是主线程)该进程中还没卸载的DLL的DllMain,且调用原因是DLL_PROCESS_DETACH。
- 加载DLL进入进程空间时(和哪个线程LoadLibrary无关),加载它的线程会调用DllMain,且调用原因是DLL_PROCESS_ATTACH。
- DLL从进程空间中卸载出去前,会被卸载其的线程调用其DllMain,且调用原因是DLL_PROCESS_DETACH。
- TerminateProcess
将导致线程和进程在退出时不对未卸载的DLL进行DllMain调用。
- ExitProcess将导致主线程意外退出,子线程对未卸载的DLL进行了DllMain调用,且调用原因是DLL_PROCESS_DETACH。
- ExitThread是最和平的退出方式,它会让线程退出前对未卸载的DLL调用DllMain。
- 线程的创建和退出不会对调用了DisableThreadLibraryCalls的DLL调用DllMain。
不要在DllMain中做的事情
在CoInitializeEx底层会调用LoadLibraryEx,原因同A。
CreateProcess在底层执行了加载DLL的操作。我用IDA查看Kernel32中的CreateProcess可以发现其底层调用的CreateProcessInternalW中有
User32和Gdi32中部分函数在调用的底层会加载其他DLL。
运行托管代码需要加载其他DLL。
理由同F。
理由同F。
- J寄希望于DisableThreadLibraryCalls解决死锁问题
Ldr对象的InMemoryOrderModuleList用户保存已经加载的DLL的链表。
它遍历这个链表,找到调用DisableThreadLibraryCalls的DLL的信息,将该信息中的Flags字段设置或上0x40000。
而创建线程在底层将调用LdrpInitializeThread(详见《DllMain中不当操作导致死锁问题的分析--DisableThreadLibraryCalls对DllMain中死锁的影响》)。该函数一开始便进入了PEB中LoaderLock临界区,在该临界区中根据PEB中LDR的InMemoryOrderModuleList遍历加载的DLL,然后判断该DLL信息的Flags字段是否或上了0x40000。如果或上了,就不调用DllMain。如果没或上,就调用DllMain。这说明DisableThreadLibraryCalls对创建线程时是否进入临界区无关。
在退出线程时底层将调用LdrShutdownThread(详见《DllMain中不当操作导致死锁问题的分析--线程退出时产生了死锁》)。该函数逻辑和LdrpInitializeThread相似,只是在调用DllMain时传的是DLL_THREAD_DETACH。所以DisableThreadLibraryCalls对LdrShutdownThread是否进入临界区也是没有影响的。
最后附上实验中的例子和《Best Practices
for Creating DLLs》
分享到:
相关推荐
DllMain和多线程死锁[归类].pdf
收集网络上关于 freelibrary 死锁 问题
error LNK2005: DllMain already defined in corelibc.lib(dllmain.obj)的解决方案
但是MFC规则DLL中却不提供DLLMAIN()函数,被MFC给封装了,Win32 DLL倒是有DLLMAIN()函数了,可是却用不了MFC,到网上找资料也很少,后来看到了一篇微软MSDN上的文章,不过是英文的(中文翻译的更看不懂了),看了之后...
关于DLLMAIN()入口函数的讨论,是讨论关于DLLMAIN()这个DLL入口函数的重要性和必要性的问题,我用VS2005列举了两个例子供大家参考.同时讨论了VC的约定的重要性,我在写这两个例子的时候就遇到同样的问题,用了一个上午的...
在做MFC的动态库时,经常会遇DllMain重定义的问题,此问题让很多开发人员十分烦恼,其实主要是自己添加的DllMain和MFC内部封装的入口函数冲突,希望此文件能帮您解决问题。
Dll动态链接库有个入口函数DllMain,这是我对DllMain的详解。 DllMain的详解:见我的博客http://blog.csdn.net/benkaoya/archive/2008/06/02/2504781.aspx
易语言让EXE程序也能拥有DllMain通知源码,可以用来监视线程的加载和销毁。@醉酒成梦°。
DllMain带有三个参数,hModule表示本dll的实例句柄(听不懂就不理它,写过windows程序的自然懂),dwReason表示dll当前所处的状态,例如DLL_PROCESS_ATTACH表示dll刚刚被加载到一个进程中,DLL_PROCESS_DETACH表示...
跟exe有个main或者WinMain入口函数一样,DLL也有一个入口函数,就是DllMain。以“DllMain”为关键字,来看看MSDN帮助文档怎么介绍这个函数的。@绿色的可达鸭。
_DllMain@12 already defined in
DLL的进入点函数DllMain
如果你要写DLL 得加一个函数DLLMain() 否则是写不成的 可以不输出,, Function DllMain(ByVal a As Long ,ByVal b As Long ,ByVal c As Long) As Long DllMain = 1 End Function 还要写个 Sub Main() 可以不...
此Dll不会导致死锁,因为它仅使用如下所述的DllMain安全的功能。 为什么? 我看到太多的POC与在DLL_PROCESS_ATTACH执行的代码。实际上,大多数情况下,恶意代码无法按照Microsoft的说明进行工作( )。 您永远不要在...
C标准库源代码\DLLMAIN.C C标准库源代码\DLL_ARGV.C C标准库源代码\DOS.H C标准库源代码\DOSMAP.C C标准库源代码\DOSPAWN.C C 标准库源代码\DOSTYPES.H C标准库源代码\DRIVE.C C标准库源代码\DRIVEMAP.C C标准库源...
有的时候,DLL并没有提供DllMain函数,应用程序也能成功引用DLL,这是因为Windows在找不到DllMain的时候,系统会从其它运行库中引入一个不做任何操作的默认DllMain函数版本,并不意味着DLL可以抛弃DllMain函数。...
4.打开项目中detoured.cpp把里面DllMain函数名修改为LengFeng(否则使用时会出现DllMain冲突)error LNK2005: _DllMain@12 already defined in ***.obj 5.直接编译就可以生成detours.lib 6.在需要的项目中使用...
驱动模拟键鼠源代码,支持64位WIN7,64位WIN7要在禁止驱动签名强制下运行 myASSoft.rar中的代码为驱动。 kmclasstest.rar中的代码为DELPHI的例子测试。注意该例子请在有还原系统的情况下使用。 否则有可能会永久安装...
不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起。 出错代码位置如下: //打开一个新的Video文件 myVideo = new Video(openFileDialog1.FileName); 去网上查了一下资料:.NET2.0中...