为什么fclose挂起/死锁? (视窗) [英] Why would fclose hang / deadlock? (Windows)

查看:457
本文介绍了为什么fclose挂起/死锁? (视窗)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个目录更改监视器进程,从一组目录中的文件读取更新。我有另一个进程,对这些目录(测试程序)的很多文件执行小写。图片大约100个目录,每个文件有10个文件,每秒大约有500个文件被修改。



运行一段时间后,目录监视进程挂起, code> fclose()在一个基本上尾随文件的方法。在这个方法中,我 fopen()文件,检查句柄是否有效,做一些寻找和读取,然后调用 fclose 。这些读取都由进程中的同一线程执行。暂停后,线程永远不会进展。



我找不到任何有关为什么 fclose()可能会死锁,而不是返回某种错误代码。文档确实提到了 _fclose_nolock(),但它似乎不适用于我(Visual Studio 2003)。



调试和发布版本都会挂起。在调试版本中,我可以看到 fclose()调用 _free_base(),在返回之前挂起。某种调用kernel32.dll => ntdll.dll => KernelBase.dll => ntdll.dll正在旋转。下面是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

解决方案

p>我发布这是一个评论,但我意识到这可能是一个答案在自己的...



基于反汇编,我猜你是覆盖由 ntdll 维护的某些内部堆结构,并且它将永远循环遍历链表。



在循环开始时,当前列表节点似乎在 ebx 中。在循环结束时,期望的最后一个节点(或终止符,如果你愿意的话 - 看起来有点像是循环列表,最后一个节点与第一个节点相同,指向这个节点的指针 [edi + 4Ch] )包含在 eax 中。很可能, cmp ebx,eax 的结果从不相等,因为列表中有一个由堆损坏引起的循环。



我不认为这与锁有关,否则我们会看到一些原子指令(例如 lock cmpxchg xchg 等)或调用其他同步函数。


I have a directory change monitor process that reads updates from files within a set of directories. I have another process that performs small writes to a lot of files to those directories (test program). Figure about 100 directories with 10 files in each, and about 500 files being modified per second.

After running for a while, the directory monitor process hangs on a call to fclose() in a method that is basically tailing the file. In this method, I fopen() the file, check that the handle is valid, do a few seeks and reads, and then call fclose(). These reads are all performed by the same thread in the process. After the hang, the thread never progresses.

I couldn't find any good information on why fclose() might deadlock instead of returning some kind of error code. The documentation does mention _fclose_nolock(), but it doesn't seem to be available to me (Visual Studio 2003).

The hang occurs for both debug and release builds. In a debug build, I can see that fclose() calls _free_base(), which hangs before returning. Some kind of call into kernel32.dll => ntdll.dll => KernelBase.dll => ntdll.dll is spinning. Here's the assembly from ntdll.dll that loops indefinitely:

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 

Any ideas what might be happening here?

解决方案

I posted this as a comment, but I realize this could be an answer in its own right...

Based on the disassembly, my guess is you've overwritten some internal heap structure maintained by ntdll, and it is looping forever iterating through a linked list.

In particular at the start of the loop, the current list node seems to be in ebx. At the end of the loop, the expected last node (or terminator, if you like -- it looks a bit like these are circular lists and the last node is the same as the first, pointer to this node being at [edi+4Ch]) is contained in eax. Probably the result of cmp ebx, eax is never equal, because there is some cycle in the list introduced by a heap corruption.

I don't think this has anything to do with locks, otherwise we would see some atomic instructions (eg. lock cmpxchg, xchg, etc.) or calls to other synchronization functions.

这篇关于为什么fclose挂起/死锁? (视窗)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆