.NET中使用StreamReader读取XML时IIS进程挂起问题排查
问题:StreamReader读取XML文件导致IIS挂起的原因分析
我们的诊断服务显示代码在读取XML文件时发生挂起,结合提供的调用栈信息及代码片段,分析导致IIS挂起的原因。
调用栈信息
STACK_TEXT: 000000e1`8225cef8 00007ffa`b93f8eb8 : 00000000`00000002 00000000`00000000 00007ffa`b1ef6cdf 000000e1`8225cdd8 : ntdll!NtReadFile+0xa 000000e1`8225cf00 00007ffa`b0b3c9c8 : 00000000`00001000 00000000`00000000 00000000`00000018 000000e1`8225d098 : KERNELBASE!ReadFile+0x74 000000e1`8225cf80 00007ffa`b0a8e803 : 000000e3`d59a39d8 000000e3`d5b65b00 000000e3`d59a3ea8 00000000`00000400 : mscorlib_ni+0x63c9c8 000000e1`8225d060 00007ffa`b0a8e75d : 000000e3`d5ec4bd8 00000000`00001000 00000000`00000000 000000ee`f3acbb90 : mscorlib_ni!System.IO.FileStream.ReadFileNative+0x83 000000e1`8225d0c0 00007ffa`b0a8e68a : 00000000`00000000 000000e3`d5b65b30 000000e3`d5b65300 00007ffa`b0a775db : mscorlib_ni!System.IO.FileStream.ReadCore+0x5d 000000e1`8225d130 00007ffa`b0b082d4 : 000000e3`d5b65b30 00007ffa`b0a8e898 00000000`00000001 000000e3`d59a39f8 : mscorlib_ni!System.IO.FileStream.Read+0x13a 000000e1`8225d190 00007ffa`b0b09fab : 00000000`00000000 00000000`00000000 00007ffa`b1f30d35 000000e1`8225cef8 : mscorlib_ni!System.IO.StreamReader.ReadBuffer+0x44 000000e1`8225d1e0 00007ffa`57ffff6d : 00007ffa`b05a5188 00000000`00000004 000000e3`d598bf58 00007ffa`52e4d508 : mscorlib_ni!System.IO.StreamReader.ReadToEnd+0x8b 000000e1`8225d230 00007ffa`57fe774a : 000000e3`d598bf58 000000e3`d59a3688 fffffff8`00000004 00000000`00000000 : Tournaments_Services!Tournaments.Services.Statistics.StatCrewService.ParseXml+0xbd
代码片段
private IGameCastGame ParseXml(string fileLocation, StatisticsType statisticsType) { XDocument xDocument; try { using (var fileStream = new FileStream( fileLocation, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (var streamReader = new StreamReader(fileStream)) { xDocument = XDocument.Parse(streamReader.ReadToEnd()); } } } catch (Exception ex) { Logger.Error(ex); return null; } return StatCrewGame.Create(xDocument, statisticsType).Parse(); }
原因分析
- 文件共享锁冲突:代码使用
FileShare.ReadWrite模式打开文件,但如果有其他进程正在对该文件进行独占写入操作,或者写入操作持续时间较长,当前读请求会被内核阻塞,线程停在ntdll!NtReadFile就是典型的内核态等待表现,直接导致线程挂起。 ReadToEnd()的阻塞风险:如果XML文件体积过大,或者文件在读取过程中被其他进程持续写入(文件内容不断增长),ReadToEnd()会一直等待读取到文件末尾,无法主动终止,造成线程长时间挂起。- 缺少IO超时机制:当前代码没有设置任何IO超时逻辑,一旦文件IO进入阻塞状态,线程会无限期等待,最终耗尽IIS线程池,引发应用整体挂起。
内容的提问来源于stack exchange,提问作者Mike Flynn
相关产品推荐
相关产品推荐

