繁体   English   中英

为什么 fclose 会挂起/死锁? (视窗)

[英]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 cmpxchgxchg等)或调用其他同步函数。

我的文件关闭 function 也有同样的情况。 在我的情况下,我通过找到嵌入的其他 function 主体而不是拥有自己的 function 来解决问题。

我也怀疑 (1) 被复制的文件的名称 (2) Windows 调度(文件 IO 在下一个任务开始之前没有完成。Windows 调度在幕后,所以它是多线程的,验证,但是当我尝试在循环中以 ASCII 格式保存许多数据时,我遇到了类似的问题。在这种情况下解决了二进制保存问题。)

我的环境,IDE:Visual Studio 2015,操作系统:Windows 7,语言:C++

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM