[英]Why would fclose hang / deadlock? (Windows)
我有一個目錄更改監視器進程,它從一組目錄中的文件中讀取更新。 我有另一個進程對這些目錄(測試程序)的大量文件執行小寫操作。 圖大約 100 個目錄,每個目錄有 10 個文件,每秒大約有 500 個文件被修改。
運行一段時間后,目錄監視器進程掛起對fclose()
的調用,該方法基本上是拖尾文件。 在此方法中,我fopen()
文件,檢查句柄是否有效,進行幾次搜索和讀取,然后調用fclose()
。 這些讀取都是由進程中的同一個線程執行的。 掛起后,線程永遠不會繼續。
我找不到任何關於為什么fclose()
可能會死鎖而不是返回某種錯誤代碼的好信息。 該文檔確實提到_fclose_nolock()
,但它似乎對我不可用(Visual Studio 2003)。
調試和發布版本都會發生掛起。 在調試版本中,我可以看到fclose()
調用_free_base()
,它在返回之前掛起。 Some kind of call into kernel32.dll => ntdll.dll => KernelBase.dll => ntdll.dll is spinning. 這是 ntdll.dll 無限循環的程序集:
77CEB83F cmp dword ptr [edi+4Ch],0
77CEB843 lea esi,[ebx-8]
77CEB846 je 77CEB85E
77CEB848 mov eax,dword ptr [edi+50h]
77CEB84B xor dword ptr [esi],eax
77CEB84D mov al,byte ptr [esi+2]
77CEB850 xor al,byte ptr [esi+1]
77CEB853 xor al,byte ptr [esi]
77CEB855 cmp byte ptr [esi+3],al
77CEB858 jne 77D19A0B
77CEB85E mov eax,200h
77CEB863 cmp word ptr [esi],ax
77CEB866 ja 77CEB815
77CEB868 cmp dword ptr [edi+4Ch],0
77CEB86C je 77CEB87E
77CEB86E mov al,byte ptr [esi+2]
77CEB871 xor al,byte ptr [esi+1]
77CEB874 xor al,byte ptr [esi]
77CEB876 mov byte ptr [esi+3],al
77CEB879 mov eax,dword ptr [edi+50h]
77CEB87C xor dword ptr [esi],eax
77CEB87E mov ebx,dword ptr [ebx+4]
77CEB881 lea eax,[edi+0C4h]
77CEB887 cmp ebx,eax
77CEB889 jne 77CEB83F
有什么想法可能在這里發生嗎?
我將此作為評論發布,但我意識到這本身可能是一個答案......
根據反匯編,我的猜測是您已經覆蓋了一些由ntdll
維護的內部堆結構,並且它永遠循環遍歷鏈表。
特別是在循環開始時,當前列表節點似乎在ebx
中。 在循環結束時,預期的最后一個節點(或終止符,如果你喜歡 - 它看起來有點像這些循環列表,最后一個節點與第一個節點相同,指向該節點的指針位於[edi+4Ch]
) 包含在eax
中。 可能cmp ebx, eax
的結果永遠不會相等,因為堆損壞引入的列表中有一些循環。
我不認為這與鎖有任何關系,否則我們會看到一些原子指令(例如lock cmpxchg
、 xchg
等)或調用其他同步函數。
我的文件關閉 function 也有同樣的情況。 在我的情況下,我通過找到嵌入的其他 function 主體而不是擁有自己的 function 來解決問題。
我也懷疑 (1) 被復制的文件的名稱 (2) Windows 調度(文件 IO 在下一個任務開始之前沒有完成。Windows 調度在幕后,所以它是多線程的,驗證,但是當我嘗試在循環中以 ASCII 格式保存許多數據時,我遇到了類似的問題。在這種情況下解決了二進制保存問題。)
我的環境,IDE:Visual Studio 2015,操作系統:Windows 7,語言:C++
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.