0

我有一个使用 .NET 4.0 开发的应用程序。此应用程序跟踪一些自定义性能计数器并显示给用户。最近我发现应用程序中存在句柄泄漏。两种类型的句柄是 Mutant 和 PcwObject。

我关注了这个页面(http://blogs.technet.com/b/yongrhee/archive/2011/12/19/how-to-troubleshoot-a-handle-leak.aspx)并得到了以下堆栈跟踪:

Handle = 0x0000000000003760 - OPEN
Thread ID = 0x00000000000073d0, Process ID = 0x0000000000005fdc

0x0000000077c41cea: ntdll!NtCreateMutant+0x000000000000000a
0x000007fefde08bf7: KERNELBASE!CreateMutexExW+0x000000000000004f
0x000007fefde14460: KERNELBASE!CreateMutexExA+0x0000000000000038
0x000007feff6bbcf6: ADVAPI32!PerflibciOpenLocalQueryHandle+0x0000000000000116
0x000007feff6a5a86: ADVAPI32!PerflibciQueryV2Provider+0x000000000000020d
0x000007feff68926d: ADVAPI32!QueryExtensibleData+0x00000000000004a2
0x000007feff6898e4: ADVAPI32!alloca_probe+0x00000000000051b2
0x00000000779d4087: KERNEL32!TlsGetValue+0x000000000000fbb8
0x00000000779e4b52: KERNEL32!RegQueryValueExW+0x00000000000000f2
0x000007feff68c2ed: ADVAPI32!RegQueryValueExWStub+0x000000000000001d
0x000007fef99b17c7: clr!DoNDirectCall__PatchGetThreadCall+0x000000000000007b
0x000007fef8a38422: mscorlib_ni+0x0000000000428422
0x000007fef89948f1: mscorlib_ni+0x00000000003848f1
0x000007fef899392e: mscorlib_ni+0x000000000038392e

Handle = 0x0000000000003998 - OPEN
Thread ID = 0x0000000000002808, Process ID = 0x0000000000005fdc

0x0000000077c4138a: ntdll!NtDeviceIoControlFile+0x000000000000000a
0x000007fefce214a3: pcwum!PcwpSendIoctl+0x00000000000000f3
0x000007fefce21962: pcwum!PcwCreateNotifier+0x000000000000003e
0x000007feff6abf53: ADVAPI32!PerfpCreateProvider+0x00000000000000d3
0x000007feff6ddb77: ADVAPI32!PerflibciLocalValidateCounters+0x0000000000000167
0x000007feff6a5ced: ADVAPI32!PerflibciQueryV2Provider+0x0000000000000478
0x000007feff68926d: ADVAPI32!QueryExtensibleData+0x00000000000004a2
0x000007feff6898e4: ADVAPI32!alloca_probe+0x00000000000051b2
0x00000000779d4087: KERNEL32!TlsGetValue+0x000000000000fbb8

我还打开了 Process Explorer 来监控句柄状态。根据我的观察,上述两个句柄(3760 和 3998)存活了半个多小时,还没有被破坏。句柄数在 2 小时内增加了约 1000 个。其中一半是 Mutant,另一半是 PcwObject。

我怀疑它与 PerformanceCounter 有关,因为我知道注册表中的 PerformanceCounter 类 grep 数据,并且我在堆栈跟踪中找到了 PerflibciQuery 和 RegQueryValue。

我已经通过互联网搜索,但似乎没有运气。有人对此有任何想法吗?谢谢

附加信息

我一一测试了那些性能计数器,发现这些句柄在获取这个计数器时被泄露了:PerformanceCounter("HTTP Service Request Queues", "CurrentQueueSize", "ABC")

我的代码是这样的:

private PerformanceCounter counter;

private void Detect()
{
    /*
    Do sth
    */

    try
    {
        if (null == counter) counter = new PerformanceCounter("HTTP Service Request Queues", "CurrentQueueSize", "ABC");
        long rawValue = counter.RawValue;
        if (0 < rawValue)
            WriteLog("ABC CurrentQueueSize: {0}", rawValue);
    }
    catch(Exception e)
    {
        WriteLog("Fail to get ABC counter. {0}", e);
    }

}

counter是一个成员变量,我很确定当这个类被销毁时它会被释放。所以我不知道为什么它会泄漏手柄。

4

2 回答 2

0

几天前我已经找到了原因,但忘记发布了。为此表示歉意。

实际上这是使用 v2 PerformanceCounter ( http://support.microsoft.com/kb/2734909 ) 导致的资源泄漏。然后我按照此页面中的说明(http://msdn.microsoft.com/en-us/library/aa392740(v=vs.85).aspx)发现“HTTP 服务请求队列”是 v2 计数器提供程序。

所以这就是原因!完毕!

于 2014-08-29T02:53:26.837 回答
0

我最近注意到的是,如果您向计数器询问不同线程中的值,则会出现句柄泄漏。如果您创建一个新线程,请向性能计数器询问下一个值,它将创建一堆不会被清理的处理,即使您处理了计数器。

于 2014-08-20T13:20:31.383 回答