多线程服务器应用程序中的COM运行时细分

时间:2014-06-13 17:24:06

标签: multithreading debugging com com-interop

我们在大型服务器应用程序中遇到COM运行时间歇性灾难性故障。

以下是我们所拥有的:

作为Windows服务运行的服务器进程托管了许多用C ++ / ATL编写的自由线程COM组件。用C ++ / MFC和.NET编写的多个客户端进程通过在同一台机器上交叉进行COM调用(包括.NET互操作)来使用这些组件。操作系统是Windows Server 2008终端服务器(32位)。 整个软件套件是内部开发的,我们有所有组件的源代码。跟踪工具包会写出操作期间生成的错误和异常。

发生了什么:

经过一段时间的平稳航行(5天到3周)后,服务器的COM运行时似乎因这些症状的任何组合而崩溃:

  • RPC_E_INVALID_HEADER(0x80010111) - " OLE收到一个包含无效标头的数据包"在对服务器组件方法的跨进程调用中返回给调用者
  • 对CLSCTX_LOCAL_SERVER上下文的CoCreateInstance(CCI)调用失败
  • CoInitializeEx(COINIT_MULTITHREADED)调用因CO_E_INIT_TLS(0x80004006)而失败

  • 所有进行中的COM活动继续运行,CCI适用于CLSCTX_INPROC_SERVER。

  • 整个系统保持响应,SQL Server正常工作,在我们的服务流程之外没有任何问题迹象。
  • 系统资源正常,没有内存泄漏,没有异常的CPU使用情况,没有颠簸

唯一的补救措施是重启破损的服务。

其他(相关)观察:

  • CPU上的核心数会产生不利影响 - 大约5天后六核Xeon盒子出现故障,较小的盒子需要3周或更长时间。
  • .NET Interop可能会涉及到,因为从.NET客户端到非托管COM服务器组件的互操作运行大量调用也会对系统产生负面影响。
  • 在服务器进程内部启用跟踪代码会延长下一次失败的工作时间。

跟踪确实引入了一些部分同步,因此可以隐藏多线程竞争条件效果。另一方面,在具有超线程的更多核上运行并行运行更多线程并增加故障率。

是否有人遇到类似的行为,甚至实际上遇到过RPC_E_INVALID_HEADER HRESULT?几乎没有关于该特定错误及其潜在原因的有用信息。 有没有办法窥探COM运行时内部以获取有关COM的私有资源池使用的更多有用信息,如内存,句柄,同步原语?可以一个过程'是否监控TLS插槽状态(CO_E_INIT_TLS)?

1 个答案:

答案 0 :(得分:3)

我们有信心将此缺陷的原因归结为.NET Framework 4.0中的资源泄漏。

我们在.NET 4.0上运行的服务器应用程序(clr.dll:4.0.30319.1)的安装显示了间歇性的COM运行时故障,可以通过将.NET框架更新到4.5.1版(clr.dll:4.0)来轻松修复。 30319.18444)

以下是我们如何找出原因:

在网络上进行的搜索在MSDN论坛中显示了一个条目:http://social.msdn.microsoft.com/Forums/pt-BR/f928f3cc-8a06-48be-9ed6-e3772bcc32e8/windows-7-x64-com-server-ole32dll-threads-are-not-cleaned-up-after-they-end-causing-com-client?forum=vcmfcatl

那里的OP描述了在使用互操作应用程序运行COM服务器一段时间(一个月左右)后,从CoCreateInstanceEx(CLSCTX_LOCAL_SERVER)接收HRESULT RPC_X_BAD_STUB_DATA(0x800706f7)。他将问题跟踪到线程资源泄漏,这可以通过ole32.dll内部的递增变量间接观察到:EventPoolEntry :: s_initState一旦其值变为0xbfff导致CCI失败...

在我们错误的安装中检查EventPoolEntry :: s_initState显示其值在大约开始时显示。重启后0x8000,然后在正常负载下运行应用程序,每小时不断增加100到200+。一旦s_initState命中0xbfff,应用程序就会因原始问题中描述的所有症状而失败。 MSDN论坛中的OP怀疑COM线程本地资源泄漏,因为他观察到对线程初始化和线程清理的非对称调用 - 5 x init与3 x cleanup。

通过在几天的过程中自动跟踪s_initState的值,我们能够证明从原始4.0将.NET框架更新到4.5.1完全消除了泄漏。