日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

DllMain中不当操作导致死锁问题的分析——DllMain中要谨慎写代码(完结篇)

發(fā)布時間:2023/11/27 生活经验 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DllMain中不当操作导致死锁问题的分析——DllMain中要谨慎写代码(完结篇) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? ? 之前幾篇文章主要介紹和分析了為什么會在DllMain做出一些不當操作導致死鎖的原因。本文將總結以前文章的結論,并介紹些DllMain中還有哪些操作會導致死鎖等問題。(轉載請指明出于breaksoftware的csdn博客)
? ? ? ??DllMain的相關特性

? ? ? ? 首先列出《DllMain中不當操作導致死鎖問題的分析--進程對DllMain函數的調用規(guī)律的研究和分析》中論證的11個特性:

  1. Dll的加載不會導致之前創(chuàng)建的線程調用其DllMain函數。
  2. 線程創(chuàng)建后會調用已經加載了的DLL的DllMain,且調用原因是DLL_THREAD_ATTACH。(DisableThreadLibraryCalls會導致該過程不被調用)
  3. TerminateThread方式終止線程是不會讓該線程去調用該進程中加載的Dll的DllMain。
  4. 線程正常退出時,會調用進程中還沒卸載的DLL的DllMain,且調用原因是DLL_THREAD_DETACH。
  5. 進程正常退出時,會調用(不一定是主線程)該進程中還沒卸載的DLL的DllMain,且調用原因是DLL_PROCESS_DETACH。
  6. 加載DLL進入進程空間時(和哪個線程LoadLibrary無關),加載它的線程會調用DllMain,且調用原因是DLL_PROCESS_ATTACH。
  7. DLL從進程空間中卸載出去前,會被卸載其的線程調用其DllMain,且調用原因是DLL_PROCESS_DETACH。
  8. TerminateProcess 將導致線程和進程在退出時不對未卸載的DLL進行DllMain調用。
  9. ExitProcess將導致主線程意外退出,子線程對未卸載的DLL進行了DllMain調用,且調用原因是DLL_PROCESS_DETACH。
  10. ExitThread是最和平的退出方式,它會讓線程退出前對未卸載的DLL調用DllMain。
  11. 線程的創(chuàng)建和退出不會對調用了DisableThreadLibraryCalls的DLL調用DllMain。

? ? ? ? 不要在DllMain中做的事情

  • A?直接或者間接調用LoadLibrary(Ex)

? ? ? ? 假如我們在A.dll中的DllMain收到DLL_PROCESS_ATTACH時,加載了B.dll;而B.dll中的DllMain在收到DLL_PROCESS_ATTACH時又去加載A.dll。則產生了循環(huán)依賴。但是注意不要想當然認為這個過程是A.dll的DllMain調用了B.dll的DllMain,B.dll的DllMain再調用了A.dll的DllMain這樣的死循環(huán)。即使不出現循環(huán)依賴,如果出現《DllMain中不當操作導致死鎖問題的分析——線程中調用GetModuleFileName、GetModuleHandle等導致死鎖》中第三個例子的情況,也會死鎖的。

  • B?使用CoInitializeEx

? ? ? ? 在CoInitializeEx底層會調用LoadLibraryEx,原因同A。

  • C?使用CreateProcess

? ? ? ? CreateProcess在底層執(zhí)行了加載DLL的操作。我用IDA查看Kernel32中的CreateProcess可以發(fā)現其底層調用的CreateProcessInternalW中有

  • D?使用User32或Gdi32中的函數

? ? ? ? User32和Gdi32中部分函數在調用的底層會加載其他DLL。

  • E?使用托管代碼

? ? ? ? 運行托管代碼需要加載其他DLL。

  • F?與其他線程同步執(zhí)行

? ? ? ? 由《DllMain中不當操作導致死鎖問題的分析--加載卸載DLL與DllMain死鎖的關系》、《DllMain中不當操作導致死鎖問題的分析--導致DllMain中死鎖的關鍵隱藏因子》和《DllMain中不當操作導致死鎖問題的分析--線程退出時產生了死鎖》可知,進程創(chuàng)建和銷毀以及DLL的加載都要進入PEB的LoadLock臨界區(qū)。如果占用了LoaderLock臨界區(qū)的線程在等待一個需要經過臨界區(qū)才能結束的線程時,就發(fā)生了死鎖。以上3篇博文中均有案例。

  • G?同步對象

?? ? ? ?如果該同步對象的釋放需要獲得PEB中的LoaderLock,而占用該臨界區(qū)的線程又要去等待這個同步對象,則會死鎖。其實F中的線程也算是個同步對象。案例詳見《DllMain中不當操作導致死鎖問題的分析——線程中調用GetModuleFileName、GetModuleHandle等導致死鎖》中例子。

  • H?使用CreateThread

? ? ? ? 理由同F。

  • I?使用ExitThread

? ? ? ?理由同F。

  • J?寄希望于DisableThreadLibraryCalls解決死鎖問題

? ? ? ? 由《DllMain中不當操作導致死鎖問題的分析--DisableThreadLibraryCalls對DllMain中死鎖的影響》可知。DisableThreadLibraryCalls的實現邏輯是:找到PEB結構中用于保存加載器信息的結構體對象Ldr。

? ? ? ? Ldr對象的InMemoryOrderModuleList用戶保存已經加載的DLL的鏈表。

? ? ? ?它遍歷這個鏈表,找到調用DisableThreadLibraryCalls的DLL的信息,將該信息中的Flags字段設置或上0x40000。

?

? ? ? ? 而創(chuàng)建線程在底層將調用LdrpInitializeThread(詳見《DllMain中不當操作導致死鎖問題的分析--DisableThreadLibraryCalls對DllMain中死鎖的影響》)。該函數一開始便進入了PEB中LoaderLock臨界區(qū),在該臨界區(qū)中根據PEB中LDR的InMemoryOrderModuleList遍歷加載的DLL,然后判斷該DLL信息的Flags字段是否或上了0x40000。如果或上了,就不調用DllMain。如果沒或上,就調用DllMain。這說明DisableThreadLibraryCalls對創(chuàng)建線程時是否進入臨界區(qū)無關。

? ? ? ? 在退出線程時底層將調用LdrShutdownThread(詳見《DllMain中不當操作導致死鎖問題的分析--線程退出時產生了死鎖》)。該函數邏輯和LdrpInitializeThread相似,只是在調用DllMain時傳的是DLL_THREAD_DETACH。所以DisableThreadLibraryCalls對LdrShutdownThread是否進入臨界區(qū)也是沒有影響的。

? ? ? ??最后附上實驗中的例子和《Best Practices for Creating DLLs》

總結

以上是生活随笔為你收集整理的DllMain中不当操作导致死锁问题的分析——DllMain中要谨慎写代码(完结篇)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。