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

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

运行一段时间之后,目录监视进程挂起一个调用fclose()的方法,该方法基本上拖尾了文件。 在这个方法中,我fopen()文件,检查句柄是否有效,做一些查找和读取,然后调用fclose() 。 这些读取全部由该进程中的相同线程执行。 挂起之后,线程永远不会前进。

我无法find关于为什么fclose()可能会死锁而不是返回某种错误代码的任何好消息。 文档确实提到了_fclose_nolock() ,但似乎并没有提供给我(Visual Studio 2003)。

debugging版本和发布版本都会发生挂起。 在一个debugging版本中,我可以看到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 

任何想法可能发生在这里?

我张贴这个评论,但我意识到这可能是一个自己的权利的答案…

基于反汇编,我的猜​​测是你已经覆盖了由ntdll维护的一些内部堆结构,并且它正在循环遍历一个链表。

特别是在循环开始时,当前列表节点似乎在ebx 。 在循环结束时,期望的最后一个节点(或终止符,如果你喜欢的话 – 看起来有点像循环列表,最后一个节点和第一个节点相同,指向这个节点的指针在[edi+4Ch] )包含在eax 。 可能是cmp ebx, eax的结果cmp ebx, eax永远不会相等,因为在堆列表中引入了一些循环。

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

我有一个与文件关闭功能相同的情况。 在我的情况下,我解决了通过定位闭合函数嵌入其他函数体而不是拥有自己的功能。

我也怀疑(1)文件被复制的名字(2)Windows调度(文件IO在下一个任务执行开始之前没有完成,Windows调度和多线程在幕后,所以很难验证,但我有类似的问题,当我试图在循环中保存ASCII数据的许多数据。

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