我如何找到挂起的终结器队列的原因? [英] How can I find the reason for a hung finalizer queue?

查看:50
本文介绍了我如何找到挂起的终结器队列的原因?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,从单词go经历了缓慢的内存泄漏.

I have an application that experiences a slow memory leak from the word go.

使用 ANTS Memory Profiler ,我可以看到所有泄漏的内存都由终结器队列的GC根保留.

Using ANTS Memory Profiler I can see that all of the leaked memory is being held by the finalizer queue's GC root.

我怀疑可能发生的事情是终结器处于死锁状态,等待锁可用.

I suspect what may have happened is that the finalizer is deadlocked waiting on a lock to become available.

我们所有的类都没有实现显式的终结器,通常应避免使用它们,这使我认为锁可能与系统或库类有关.

None of our classes implement explicit finalizers, we avoid them as a rule, this makes me think the lock might related to a system or library class.

我已经使用过 SOS.dll 来查看终结器队列的内容,如果我正确地解释了它,则它报告的第一项是实例 System.Threading.Thread 但是,我不确定队列的开头是否实际上代表当前正在处理的对象还是下一个要处理的对象.

I've used SOS.dll to take a look at the contents of the finalizer queue and if I am interpreting it correctly then it reports the first item to be an instance System.Threading.Thread However I am unsure if the head of the queue actually represents the currently being disposed object or the next object to be disposed.

  • 我有什么技巧可以用来确定正在确定的内容吗?
  • 有没有办法找出终结器线程正在等待的锁?
  • 是否可以打开任何额外的调试来跟踪终结器线程的操作?
  • 我还能看什么?

更新

终结器线程的堆栈如下所示:

The finalizer thread's stack appears as follows:

ntdll.dll!_ZwWaitForSingleObject@12()  + 0x15 bytes  
ntdll.dll!_ZwWaitForSingleObject@12()  + 0x15 bytes  
user32.dll!_NtUserPostMessage@16()  + 0x15 bytes     

kernel32.dll!_WaitForSingleObjectExImplementation@12()  + 0x43 bytes     
kernel32.dll!_WaitForSingleObject@8()  + 0x12 bytes  
ole32.dll!GetToSTA()  + 0x72 bytes   

ole32.dll!CRpcChannelBuffer::SwitchAptAndDispatchCall()  - 0x1939 bytes  
ole32.dll!CRpcChannelBuffer::SendReceive2()  + 0xa6 bytes    
ole32.dll!CAptRpcChnl::SendReceive()  + 0x5b7 bytes  
ole32.dll!CCtxComChnl::SendReceive()  - 0x14b97 bytes    
ole32.dll!NdrExtpProxySendReceive()  + 0x43 bytes    
rpcrt4.dll!@NdrpProxySendReceive@4()  + 0xe bytes    
rpcrt4.dll!_NdrClientCall2()  + 0x144 bytes  
ole32.dll!_ObjectStublessClient@8()  + 0x7a bytes    
ole32.dll!_ObjectStubless@0()  + 0xf bytes   

ole32.dll!CObjectContext::InternalContextCallback()  - 0x511f bytes  
ole32.dll!CObjectContext::ContextCallback()  + 0x8f bytes    
clr.dll!CtxEntry::EnterContext()  + 0x119 bytes  

clr.dll!RCWCleanupList::ReleaseRCWListInCorrectCtx()  + 0x2bb bytes  

clr.dll!RCWCleanupList::CleanupAllWrappers()  - 0x20fb0 bytes    
clr.dll!SyncBlockCache::CleanupSyncBlocks()  + 0x1ec6 bytes  
clr.dll!Thread::DoExtraWorkForFinalizer()  + 0x411b5 bytes   

clr.dll!WKS::GCHeap::FinalizerThreadWorker()  + 0x8b bytes   
clr.dll!Thread::DoExtraWorkForFinalizer()  + 0xb6e76 bytes   
clr.dll!Thread::ShouldChangeAbortToUnload()  - 0x5f8 bytes   
clr.dll!Thread::ShouldChangeAbortToUnload()  - 0x53d bytes   
clr.dll!ManagedThreadBase_NoADTransition()  + 0x35 bytes     
clr.dll!ManagedThreadBase::FinalizerBase()  + 0xf bytes  
clr.dll!WKS::GCHeap::FinalizerThreadStart()  + 0xfb bytes    
clr.dll!Thread::intermediateThreadProc()  + 0x48 bytes   
kernel32.dll!@BaseThreadInitThunk@12()  + 0x12 bytes     
ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes    
ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes     

推荐答案

在我看来,您在使用COM服务器时遇到了问题.调用堆栈显示它正在尝试在单线程COM对象上进行IUnknown :: Release()调用.ReleaseRCWListInCorrectCtx()调用将其设置为关闭,_NtUserPostMessage @ 16()是将请求封送给拥有COM对象的STA的调用.

Looks to me you are having a problem with a COM server. The call stack shows it is trying to make the IUnknown::Release() call on a single-threaded COM object. The ReleaseRCWListInCorrectCtx() call sets it off, the _NtUserPostMessage@16() is the call that marshals the request to the STA that owns the COM object.

典型的原因是创建COM对象,而不是发送消息循环.对STA线程的严格要求.通过在主UI线程上创建它们并从不对其进行阻止,可以避免这种情况.

The typical cause is creating COM objects and not pumping a message loop. A hard requirement for STA threads. You avoid it by creating them on the main UI thread and never blocking it.

这篇关于我如何找到挂起的终结器队列的原因?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆