Dom*_*que 8 c# multithreading garbage-collection dump windows-server-2016
我面临着一个 .Net 服务器应用程序,该应用程序几乎每周都会因“GC Finalizer Thread”中的问题而崩溃,更准确地说是在“mscorlib.dll ...~DestroyScout()”的第 798 行,根据视觉工作室。
Visual Studio 还尝试打开文件“DynamicILGenerator.gs”。我没有这个文件,但我找到了该文件的一个版本,其中第 798 行确实位于析构函数或DestroyScout(无论这可能意味着什么)内部。
我的 Visual Studio 环境中有以下信息:
主题:
Not Flagged > 5892 0 Worker Thread GC Finalizer Thread mscorlib.dll!System.Reflection.Emit.DynamicResolver.DestroyScout.~DestroyScout
Run Code Online (Sandbox Code Playgroud)
调用堆栈:
[Managed to Native Transition]
> mscorlib.dll!System.Reflection.Emit.DynamicResolver.DestroyScout.~DestroyScout() Line 798 C#
[Native to Managed Transition]
kernel32.dll!@BaseThreadInitThunk@12() Unknown
ntdll.dll!__RtlUserThreadStart() Unknown
ntdll.dll!__RtlUserThreadStart@8() Unknown
Run Code Online (Sandbox Code Playgroud)
当地人(无法确定该$exception对象是否正确):
+ $exception {"Exception of type 'System.ExecutionEngineException' was thrown."} System.ExecutionEngineException
this Cannot obtain value of the local variable or argument because it is not available at this instruction pointer,
possibly because it has been optimized away. System.Reflection.Emit.DynamicResolver.DestroyScout
Stack objects No CLR objects were found in the stack memory range of the current frame.
Run Code Online (Sandbox Code Playgroud)
“DynamicILGenerator.cs”的源代码,提到了该类DestroyScout(注释中提到了第 798 行):
private class DestroyScout
{
internal RuntimeMethodHandleInternal m_methodHandle;
[System.Security.SecuritySafeCritical] // auto-generated
~DestroyScout()
{
if (m_methodHandle.IsNullHandle())
return;
// It is not safe to destroy the method if the managed resolver is alive.
if (RuntimeMethodHandle.GetResolver(m_methodHandle) != null)
{
if (!Environment.HasShutdownStarted &&
!AppDomain.CurrentDomain.IsFinalizingForUnload())
{
// Somebody might have been holding a reference on us via weak handle.
// We will keep trying. It will be hopefully released eventually.
GC.ReRegisterForFinalize(this);
}
return;
}
RuntimeMethodHandle.Destroy(m_methodHandle); // <===== line 798
}
}
Run Code Online (Sandbox Code Playgroud)
监视窗口 ( m_methodHandle):
m_methodHandle Cannot obtain value of the local variable or argument because
it is not available at this instruction pointer,
possibly because it has been optimized away.
System.RuntimeMethodHandleInternal
Run Code Online (Sandbox Code Playgroud)
一般转储模块信息:
Dump Summary
------------
Dump File: Application_Server2.0.exe.5296.dmp : C:\Temp_Folder\Application_Server2.0.exe.5296.dmp
Last Write Time: 14/06/2022 19:08:30
Process Name: Application_Server2.0.exe : C:\Runtime\Application_Server2.0.exe
Process Architecture: x86
Exception Code: 0xC0000005
Exception Information: The thread tried to read from or write to a virtual address
for which it does not have the appropriate access.
Heap Information: Present
System Information
------------------
OS Version: 10.0.14393
CLR Version(s): 4.7.3920.0
Modules
-------
Module Name Module Path Module Version
----------- ----------- --------------
...
clr.dll C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll 4.7.3920.0
...
Run Code Online (Sandbox Code Playgroud)
请注意:转储到达了Windows-Server 2016计算机,我正在调查 Windows-10 环境中的转储(不要OS Version在转储摘要中弄错)!
毁灭侦察兵可能会试图摧毁什么?这可能很有趣。
我不知道到底是什么导致了这次崩溃,但我可以告诉你到底是什么DestroyScout造成的。
它与创建动态方法有关。该类DynamicResolver需要清理相关的非托管内存,这些内存不被GC跟踪。但直到绝对不再有对该方法的引用之前,它无法被清理。
但是,因为恶意(或完全奇怪的)代码可以使用可以在 GC 中幸存的 long ,因此在其终结器运行后WeakReference恢复对动态方法的引用。因此,它带有奇怪的代码,以确保它是最后一个被销毁的引用。DestroyScoutGC.ReRegisterForFinalize
源码中的注释中有解释
// We can destroy the unmanaged part of dynamic method only after the managed part is definitely gone and thus
// nobody can call the dynamic method anymore. A call to finalizer alone does not guarantee that the managed
// part is gone. A malicious code can keep a reference to DynamicMethod in long weak reference that survives finalization,
// or we can be running during shutdown where everything is finalized.
//
// The unmanaged resolver keeps a reference to the managed resolver in long weak handle. If the long weak handle
// is null, we can be sure that the managed part of the dynamic method is definitely gone and that it is safe to
// destroy the unmanaged part. (Note that the managed finalizer has to be on the same object that the long weak handle
// points to in order for this to work.) Unfortunately, we can not perform the above check when out finalizer
// is called - the long weak handle won't be cleared yet. Instead, we create a helper scout object that will attempt
// to do the destruction after next GC.
Run Code Online (Sandbox Code Playgroud)
至于你的崩溃,这是在内部代码中发生的,并导致ExecutionEngineException. 当内存损坏、内存以不应该的方式使用时,最有可能发生这种情况。
内存损坏的发生有多种原因。按照可能性的顺序:
DllImport以及相关的编组)。unsafe(包括库类,例如Unsafe和 ,Buffer它们做同样的事情)。考虑将崩溃报告提交给 Microsoft 进行调查。
作者编辑:
为了向 Microsoft 提交崩溃报告,可以使用以下 URL: https: //www.microsoft.com/en-us/unifiedsupport。请考虑到这是一项付费服务,您可能需要向 Microsoft 提供整个源代码才能获得对故障转储的完整分析。