【问题标题】:.NET application handle leak, how to locate the source?.NET 应用程序句柄泄漏,如何定位源头?
【发布时间】:2017-05-06 13:57:10
【问题描述】:

我有一个在生产环境 (WINDOWS XP + .NET 3.5 SP1) 中运行的 .NET 应用程序,其句柄数稳定在 2000 左右,但在某些未知情况下,它的句柄数会以极快的速度增加并最终自行崩溃(超过 10,000由 PerfMon 工具监控)。

我在增加期间从那里进行了内存转储(尚未崩溃)并导入到WinDbg,可以看到整体句柄摘要:

0:000> !handle 0 0
7229 Handles
Type            Count
None            19
Event           504
Section         6108
File            262
Port            15
Directory       3
Mutant          56
WindowStation   2
Semaphore       70
Key             97
Token           2
Process         3
Thread          75
Desktop         1
IoCompletion    9
Timer           2
KeyedEvent      1


  

所以不足为奇,泄漏类型是 Section,请继续挖掘:

0:000> !handle 0 ff Section
Handle 00007114
  Type          Section
  Attributes    0
  GrantedAccess 0xf0007:
         Delete,ReadControl,WriteDac,WriteOwner
         Query,MapWrite,MapRead
  HandleCount   2
  PointerCount  4
  Name          \BaseNamedObjects\MSCTF.MarshalInterface.FileMap.IBC.AKCHAC.CGOOBGKD
  No object specific information available
Handle 00007134
  Type          Section
  Attributes    0
  GrantedAccess 0xf0007:
         Delete,ReadControl,WriteDac,WriteOwner
         Query,MapWrite,MapRead
  HandleCount   2
  PointerCount  4
  Name          \BaseNamedObjects\MSCTF.MarshalInterface.FileMap.IBC.GKCHAC.KCLBDGKD
  No object specific information available

...
...
...
...
6108 handles of type Section

可以看到BaseNamedObjects'的命名约定都是MSCTF.MarshalInterface.FileMap.IBC.***.*****。

基本上我被拦在了这里,无法进一步将信息链接到我的应用程序。

有人可以帮忙吗?

[编辑0]

尝试了GFlags 命令的几种组合(+ust 或通过 UI),但没有成功,使用 WinDbg 打开的转储总是通过!htrace 看不到任何内容,因此必须使用 附加进程最后我得到了上面泄漏句柄的堆栈:

0:033> !htrace 1758
--------------------------------------
Handle = 0x00001758 - OPEN
Thread ID = 0x00000768, Process ID = 0x00001784

0x7c809543: KERNEL32!CreateFileMappingA+0x0000006e
0x74723917: MSCTF!CCicFileMappingStatic::Create+0x00000022
0x7473fc0f: MSCTF!CicCoMarshalInterface+0x000000f8
0x747408e9: MSCTF!CStub::stub_OutParam+0x00000110
0x74742b05: MSCTF!CStubIUnknown::stub_QueryInterface+0x0000009e
0x74743e75: MSCTF!CStubITfLangBarItem::Invoke+0x00000014
0x7473fdb9: MSCTF!HandleSendReceiveMsg+0x00000171
0x7474037f: MSCTF!CicMarshalWndProc+0x00000161
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\system32\USER32.dll - 
0x7e418734: USER32!GetDC+0x0000006d
0x7e418816: USER32!GetDC+0x0000014f
0x7e4189cd: USER32!GetWindowLongW+0x00000127
--------------------------------------

然后我又卡住了,堆栈似乎没有包含我们的任何用户代码,有什么建议可以继续前进?

【问题讨论】:

标签: windows performance memory-leaks windbg


【解决方案1】:

WinDbg 不是解决内存泄漏的理想工具,尤其是在没有提前准备的情况下。

有一个 GFlags 选项 (+ust) 可以启用,以便进程记录句柄分配的堆栈跟踪。如果您没有启用此标志,您可能无法从转储中获得更多信息。如果有,请使用!htrace 查看堆栈。

您也可以尝试UMDH (user mode dump heap),这是一个免费工具。或者获得类似memory validator 的东西,它肯定具有更好的可用性,所以从长远来看它可能会有所回报。

【讨论】:

  • 所以基本上我需要在生产机器中更改一些配置,并等待另一轮问题重新生成。我更喜欢按照您的建议启用GFlags 和+ust。
  • @Shawn:是的,这应该是下一步。如果您有更多信息,您可以编辑您的问题(确保通知我,因为不会自动提醒我)或提出一个新问题(取决于它改变了多少范围)。
  • @Weller 我已经在生产机器上部署了WinDbg和GFlags,并通过命令gflags /i "C:\Program Files\xxxx\abc.exe" +ust对我们的应用程序启用了GFlags,然后通过单击应用程序图标运行应用程序,运行一段时间后,从Process explorer 创建一个full dump,然后将转储导入WinDbg,输入!htrace,什么都不显示,我哪里出错了?或者我必须将WinDbg附加到应用程序,这将大大降低我们应用程序的响应,基本上客户不会允许这样做。
  • @Shawn:一个故障转储就足够了,不需要附加调试器。不过,我从来没有使用带有完整路径的 GFlags,只是可执行文件名。如果您有很多句柄,则可能没有足够的空间容纳所有句柄,因此请使用 /tracedb 增加数据库大小
  • @Weller 我已经尝试过gflags /i abc.exe +ust,但我使用的ADPlus 中的内存转储模式是Hang,因为我等不及应用程序崩溃了(结束10 天),现在更重要的是,我需要做一些测试以确保句柄堆栈跟踪包含在转储中。所以基于上述操作,!htrace 命令在hang 转储上仍然没有显示,知道吗?
猜你喜欢
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
  • 2013-06-10
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多