DllMain中不当操作导致死锁问题的分析——线程中调用GetModuleFileName、GetModuleHandle等导致死锁
? ? ? ? 之前的幾篇文章已經講解了在DllMain中創建并等待線程導致的死鎖的原因。是否還記得,我們分析了半天匯編才知道在線程中的死鎖位置。如果對于缺乏調試經驗的同學來說,可能發現這個位置有點麻煩。那么本文就介紹幾個例子,它們會在線程明顯的位置死鎖掉。(轉載請指明出于breaksoftware的csdn博客)
? ? ? ? DLL中的代碼依舊簡單。它獲取叫EVENT的命名事件,然后等待這個事件被激活。激活的操作自然放在線程中。這次我們不用在DLL中創建線程,而是在Exe中創建。
switch (ul_reason_for_call) {case DLL_PROCESS_ATTACH: {printf("DLL DllGetModuleHandle:\tProcess attach (tid = %d)\n", tid);HANDLE hEvent = CreateEvent( NULL, FALSE, FALSE, L"EVENT" );if ( NULL != hEvent ) {WaitForSingleObject(hEvent, INFINITE);}}break;
? ? ? ? 1 線程中調用GetModuleFileName死鎖
? ? ? ? 線程函數是
static DWORD WINAPI ThreadGetModuleFileName(LPVOID h) {HMODULE hDll = (HMODULE)h;WCHAR wszFileName[MAX_PATH] = {0};GetModuleFileName( hDll, wszFileName, MAX_PATH );HANDLE hEvent = CreateEvent( NULL, FALSE, FALSE, L"EVENT" );SetEvent( hEvent );return 0;
}
? ? ? ? 死鎖后,DLL中的死鎖位置和前幾篇文章中一樣,本文之后均不再說明。我們關注線程的堆棧,它是
? ? ? ??我們看到GetModuleFileName在內部要調用LdrLockLoderLock,以進入PEB的LoaderLock臨界區。可是該臨界區被主線程占用著(在調用DllMain前進入臨界區),主線程還要等待工作線程調用GetModuleFileName后激活事件才退出,于是就死鎖了。
? ? ? ?2?線程中調用GetModuleHandle死鎖
? ? ? ? 線程函數是
static DWORD WINAPI ThreadGetModuleHandle(LPVOID) {Sleep(1000);GetModuleHandle( L"DllWithoutDisableThreadLibraryCalls_A.dll" );HANDLE hEvent = CreateEvent( NULL, FALSE, FALSE, L"EVENT" );SetEvent( hEvent );return 0;
}
? ? ? ? 內容我就不說明了,我們直接看線程堆棧。
? ? ? ? 我們看到GetModuleHandleW底層還是進入了加載器函數中。并在加載器函數中進入了LdrLockLoderLock,該函數內部要進入PEB的LoaderLock臨界區。可是該臨界區被主線程占用著(在調用DllMain前進入臨界區),主線程還要等待工作線程調用GetModuleHandle后激活事件才退出,于是就死鎖了。
? ? ? ? 3?線程中調用LoadLibrary死鎖
? ? ? ? 線程函數
static DWORD WINAPI ThreadLoadLibrary(LPVOID) {Sleep(1000);LoadLibraryW( L"DllWithoutDisableThreadLibraryCalls_A.dll" );HANDLE hEvent = CreateEvent( NULL, FALSE, FALSE, L"EVENT" );SetEvent( hEvent );return 0;
}
? ? ? ? 死鎖后線程堆棧
總結
以上是生活随笔為你收集整理的DllMain中不当操作导致死锁问题的分析——线程中调用GetModuleFileName、GetModuleHandle等导致死锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DllMain中不当操作导致死锁问题的分
- 下一篇: DllMain中不当操作导致死锁问题的分