我们已经面临一个非常棘手的问题将近一周了,但我们仍然无法解决它。
问题是,我们在IIS上有一个应用程序池,它每天崩溃并回收几次。
我们监控了事件查看器上发生的事情,但那里的错误不够详细。
来自windows事件查看器的2个错误(间隔2秒)示例:
错误1:
Event Id : 1000
An unhandled exception occurred and the process was terminated.
Application ID: /LM/W3SVC/20/ROOT
Process ID: 14300
Exception: System.ObjectDisposedException
Message: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
StackTrace: at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.FtpClient.FtpSocketStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.Net.FtpClient.FtpSocketStream.WriteLine(Encoding encoding, String buf)
at System.Net.FtpClient.FtpClient.Execute(String command)
at System.Net.FtpClient.FtpClient.Disconnect()
at System.Net.FtpClient.FtpClient.Dispose()
at System.Net.FtpClient.FtpClient.Finalize()
错误2:
事件Id:1325
Faulting application name: w3wp.exe, version: 8.5.9600.16384, time stamp: 0x52157ba0
Faulting module name: KERNELBASE.dll, version: 6.3.9600.18666, time stamp: 0x58f32841
Exception code: 0xe0434352
Fault offset: 0x00015608
Faulting process id: 0x37dc
Faulting application start time: 0x01d35b56102b1ddf
Faulting application path: C:windowsSysWOW64inetsrvw3wp.exe
Faulting module path: C:windowsSYSTEM32KERNELBASE.dll
Report Id: b9f70358-c76a-11e7-8111-0cc47a0c4e39
Faulting package full name:
Faulting package-relative application ID:
此时此刻,我们能够发现是哪个错误导致应用程序池崩溃。它涉及从FtpClient库访问已处理的对象。但我们仍然无法在代码中找到执行这种调用的内容。
然后,我们决定安装DebugDiag(https://www.microsoft.com/en-us/download/details.aspx?id=49924)。顺便说一句,这是一个非常强大的工具。我们启动了用于监控应用程序池崩溃的DebugDiag,并能够生成一个非常详细的报告(.mhtml格式)。
以下是完整的调用堆栈:.NET调用堆栈
[[HelperMethodFrame]]
System_ni!System.Net.Sockets.NetworkStream.Write(Byte[], Int32, Int32)+673bde
System.Net.FtpClient.FtpSocketStream.Write(Byte[], Int32, Int32)+33
System.Net.FtpClient.FtpSocketStream.WriteLine(System.Text.Encoding, System.String)+44
System.Net.FtpClient.FtpClient.Execute(System.String)+1c6
System.Net.FtpClient.FtpClient.Disconnect()+57
System.Net.FtpClient.FtpClient.Dispose()+46
System.Net.FtpClient.FtpClient.Finalize()+10
[[DebuggerU2MCatchHandlerFrame]]
[[ContextTransitionFrame]]
[[GCFrame]]
[[DebuggerU2MCatchHandlerFrame]]
完整调用堆栈
KERNELBASE!RaiseException+48
clr!RaiseTheExceptionInternalOnly+27c
clr!IL_Throw+141
[[HelperMethodFrame]]
System_ni!System.Net.Sockets.NetworkStream.Write(Byte[], Int32, Int32)+673bde
System.Net.FtpClient.FtpSocketStream.Write(Byte[], Int32, Int32)+33
System.Net.FtpClient.FtpSocketStream.Write(Byte[], Int32, Int32)+33
System.Net.FtpClient.FtpSocketStream.WriteLine(System.Text.Encoding, System.String)+44
System.Net.FtpClient.FtpSocketStream.WriteLine(System.Text.Encoding, System.String)+44
System.Net.FtpClient.FtpClient.Execute(System.String)+1c6
System.Net.FtpClient.FtpClient.Disconnect()+57
System.Net.FtpClient.FtpClient.Dispose()+46
System.Net.FtpClient.FtpClient.Finalize()+10
clr!MethodTable::FastBox+b0
clr!MethodTable::CallFinalizer+139
clr!CallFinalizer+a6
clr!FinalizerThread::FinalizeAllObjects+a6
clr!FinalizerThread::FinalizeAllObjects_Wrapper+14
clr!Thread::DoExtraWorkForFinalizer+1b1
clr!Thread::DoExtraWorkForFinalizer+234
clr!Thread::DoExtraWorkForFinalizer+5f8
[[DebuggerU2MCatchHandlerFrame]]
clr!Thread::DoExtraWorkForFinalizer+137
clr!Thread::DoADCallBack+30f
[[ContextTransitionFrame]]
clr!Thread::DoExtraWorkForFinalizer+19f
clr!FinalizerThread::DoOneFinalization+129
[[GCFrame]]
clr!FinalizerThread::FinalizeAllObjects+a6
clr!FinalizerThread::FinalizerThreadWorker+ed
clr!Thread::DoExtraWorkForFinalizer+1b1
clr!Thread::DoExtraWorkForFinalizer+234
clr!Thread::DoExtraWorkForFinalizer+5f8
[[DebuggerU2MCatchHandlerFrame]]
clr!ManagedThreadBase::FinalizerBase+33
clr!FinalizerThread::FinalizerThreadStart+d4
clr!Thread::intermediateThreadProc+55
kernel32!BaseThreadInitThunk+24
ntdll!__RtlUserThreadStart+2f
ntdll!_RtlUserThreadStart+1b
我们能够找到导致池崩溃的异常,但我们仍然无法找到代码的哪一部分正在进行调用。在调用堆栈的底部,您可以注意到第一个事件是:ntdll_RtlUserThreadStart+1b,我真的不知道。。
所以我很高兴能得到一些帮助来解决这两个问题:
- 如何在我的代码中找到创建bug的原因
- 这样的错误怎么会使我的应用程序池崩溃并回收
环境:-IIS 8.5-应用程序池CLR版本4-Windows Server 2012 R2
消息Cannot access a disposed object
表示垃圾收集器已经处理了您的对象,然后您将尝试使用该对象。
你用using
调用FtpClient吗?你在做.close()
吗?
错误日志实际上并不有用,如果你发布你的代码会更好。
此外,将代码放在try...catch
中,这样您就可以捕获错误,而不是让它不被处理。有时文件传输失败,因此您需要执行以下操作:
try {
using(Stream s = ftpClient.OpenRead()) {
// perform your transfer
}
}
catch(Exception) {
// Typical exceptions here are IOException, SocketException, or a FtpCommandException
}