背景
有些客户反应客户端程序操作一段时间后,查看任务管理器发现客户端程序占用句柄数过多,怀疑存在句柄泄露问题。针对该问题,现场测试多个场景,把出现问题的范围缩小。现发现在以下两个场景下,会出现句柄泄露:
1、 打开客户端程序后操作交易
2、 在文本框中切换输入法(百度输入法2.10版本)
使用handle.exe收集数据并分析后,已经确定是由于客户端程序中使用键盘钩子与百度输入法自带Bug导致句柄泄露,但排查时还是浪费了大量时间,几经转折才查出原因。下面说明下如何使用Windbg来准确快速的定位问题。
排查步骤
首先,什么是句柄,微软是如下描述的:
An object is a data structure that represents a system resource, such as a file, thread, or graphic image. An application cannot directly access object data or the system resource that an object represents. Instead, an application must obtain an object handle, which it can use to examine or modify the system resource. Each handle has an entry in an internally maintained table. These entries contain the addresses of the resources and the means to identify the resource type
排查问题主要分下面几步:
1、安装Windbg工具
2、运行存在问题的应用程序
3、Windbg连接该程序
4、执行“!htrace –enable“命令,打开堆栈追踪
5、执行“!htrace -snapshot”命令,建立快照
6、开始Debug,操作应用程序
7、停止Debug,执行“!htrace -diff”命令,找到泄露句柄的堆栈信息
下面具体说明下每一步操作,前两步不在赘述,从第3步开始
如下图所示,连接该应用程序
执行“!htrace –enable“与“!htrace -snapshot”命令
选择Debug中的“Go”,按句柄增加的场景操作应用程序,并观察任务管理器中的句柄数
观察到任务管理器中的句柄数增加后,停止Debug
执行“!htrace -diff”命令,可以看到该句柄及申请句柄的程序堆栈信息,下面的图片中可以直接看到是“swt_extension_win32”的”HookProc”方法申请的句柄。现在问题已经可以确定是由于此处导致。
执行“!handle xx f”命令,可以看到该句柄与handle.exe工具收集到的信息一致
同样,切换输入法时句柄增加可以得到下图数据,可以看到是“UIPFull”的”DllCanUnloadNow”方法申请的句柄
打开百度输入法安装目录,可以看到如下信息,从而可以确定本次泄露是由百度输入法导致:
总结
应用程序在出现句柄泄露时会引起一定的恐慌,误认为此问题会比较严重,从而对查找问题造成一定的干扰。其实,句柄泄露并不可怕,客户端在存在句柄泄露问题的情况下,依旧可以长时间稳定高效运行。不过查出句柄泄露原因还是很有必要的,查找时可使用handle.exe与windbg配合来使用,先确定出现泄露的场景,然后使用工具在该场景中收集数据,分析问题。
备注
注意事项:
使用”!htrace –diff”命令时,在安装win8系统的机器上无法打印出堆栈信息,XP系统的机器上可以打印完整信息。
参考链接:
javascript:void(0)
https://msdn.microsoft.com/en-us/library/windows/hardware/ff563208(v=vs.85).aspx
Windbg可以从微软官网下载~