平台服务器句柄泄露问题的排查与解决

我们监控平台有台报警服务器,其主要功能是接收前端,TDDC,网管服务器等发送的报警,并依据报警联动配置进行相应的联动操作,最近发现在该服务器运行过程中,通过任务管理器查看其句柄数量会不断增加,以至于影响其他服务器工作,初步怀疑是句柄泄露问题,现对其进行分析排查。

句柄是Windows用来标识应用程序所建立或使用的对象的唯一整数,Windows的内核对象包括进线程,窗口,位图,GDI对象等等。应用程序通过句柄访问内核对象,当使用完内核对象之后需要释放资源关闭该内核对象句柄,如果未能正确关闭,则会造成句柄泄露。

一般而言,如果怀疑发生了句柄泄露,最首要任务是查找泄露的句柄类型,这样有助于后面的排查分析,缩小目标范围。这时可以通过一些辅助工具来帮助分析,如Process Explorer,PCHunter等,这些工具能够非常明了的看到进程所正在使用的内核对象,可以帮助我们找到问题所在。

打开Process Explorer,找到运行的报警服务器进程,该工具的会显示出报警服务器当前创建的内核对象句柄,如图,可以看出该进程的句柄数已经有上千个,而且还在快速增长中。

该工具很方便的一点是,当有新的内核对象创建时,在下方的列表框中会以绿色标识出来,方便查看,观察一段时间发现,不停的有线程对象创建,而且不会关闭,初步猜测应该是线程对象的句柄没有关闭导致。接下来的工作就是要找出这个线程内核对象在哪儿创建的。

查找句柄的创建位置的可以通过windbg来获取,windbg是windows下一款非常强大的内核调试器。使用Windbg的!htrace命令可以调试句柄泄露。其原理比较简单,就是分别为进程的内核对象做两次快照,比较这两次的不同,就可以知道有哪些内核对象创建了,同时还能找到是在哪儿分配的。

打开windbg,按F6,附加报警服务器进程。在命令行里面输入!htrace–enable开启htrace功能。输入!htrace –snapshot做第一个快照,然后输入g命令,让程序执行一段时间。

该过程如下图所示:

程序运行一段时间后,按Ctrl+Break键,将程序中断下来。这时输入!handle –diff,可以比较新增句柄的分配上下文。

通过仔细观察,可以看出,有创建了多个线程内核对象,查看一个内核对象的信息可以使用!handle命令。例如查看handle值为f98的线程内核对象,可输入!handlef98 ff。如下图所示

其起始地址为HPR_GetNetWorkFlowData,可以确定该线程是使用HPR库创建的,可以通过在源代码中查找HPR_Thread_Create来缩小范围。

再图中还可以看到线程ID为7670.fef4,其中7670为进程ID,fef4是线程ID,因此可以切换到该线程看看,输入

~~[fef4]s命令,切换线程。

出现了一条错误信息,即该线程已经不存在了,那其实我们就基本可以确定这里发生了泄露,线程已经不复存在,但该线程的内核对象却未能关闭。

通过仔细观察,我们可以看到这些线程对象都是同一个线程创建的,如图

最终都指向了71a8这个线程,这样我们可以确定是71a8这个线程创建了很多线程内核对象,却没有将内核对象的句柄关闭,这样造成了线程内核对象的句柄泄露,只要定位到71a8这个线程,就能找到泄露的地方。

输入~~[71a8]s,切换到这个线程,并输入kb打印其调用栈,如下图:

调用栈是一堆非常奇怪的数据,其实是因为我的系统是64位的,而报警服务器这个进程是32位的,windbg使用64位的上下文去解析32位的进程,造成了错误的解析。这时可以通过!sw这条命令来切换至32位的上下文。然后再敲入kb命令,就能看到该线程的调用栈了,如图:

可以清楚的看到该线程的调用栈,此时该线程正在等待socket连接,使用的是HPR库的HPR_Accept函数,到这个地步,在源代码中定位该线程函数就非常容易了。

在源代码中搜索HPR_Accept函数,只有一个地方:

可以清楚的看到,这个线程接受到连接之后,就创建了一个线程,不过却未将创建线程的句柄关闭,从而造成了句柄泄露,这与我们之前分析的一致。知道了问题所在,修改也就很方便了。

引自:http://blog.csdn.net/shuizhilan/article/details/46632083

时间: 2024-12-21 21:12:01

平台服务器句柄泄露问题的排查与解决的相关文章

服务器CPU使用率过高排查与解决思路

发现服务器的cpu使用率特别高 排查思路: -使用top或者mpstat查看cpu的使用情况# mpstat -P ALL 2 1Linux 2.6.32-358.el6.x86_64 (linux—host) 01/05/2016 _x86_64_ (24 CPU) 04:41:13 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle04:41:15 PM all 0.56 0.00 0.25 0.00 0.00 0.04

客户端程序出现句柄泄露时查找办法

背景 有些客户反应客户端程序操作一段时间后,查看任务管理器发现客户端程序占用句柄数过多,怀疑存在句柄泄露问题.针对该问题,现场测试多个场景,把出现问题的范围缩小.现发现在以下两个场景下,会出现句柄泄露: 1. 打开客户端程序后操作交易 2. 在文本框中切换输入法(百度输入法2.10版本) 使用handle.exe收集数据并分析后,已经确定是由于客户端程序中使用键盘钩子与百度输入法自带Bug导致句柄泄露,但排查时还是浪费了大量时间,几经转折才查出原因.下面说明下如何使用Windbg来准确快速的定位

linux句柄泄露问题查看

背景: 我们在开发linux在线服务器的时候经常会遇会句柄泄露的问题.因为在linux系统设计里面遵循一切都是文件的原则,即磁盘文件.目录.网络套接字.磁盘.管道等,所有这些都是文件,在我们进行打开的时候会返回一个fd,即是文件句柄.如果频繁的打开文件,或者打开网络套接字而忘记释放就会有句柄泄露的现象.在linux系统中对进程可以调用的文件句柄数进行了限制,在默认情况下每个进程可以调用的最大句柄数是1024个,如果超过了这个限制,进程将无法获取新的句柄,而从导致不能打开新的文件或者网络套接字,对

.NET对象与Windows句柄(三):句柄泄露实例分析

在上篇文章.NET对象与Windows句柄(二):句柄分类和.NET句柄泄露的例子中,我们有一个句柄泄露的例子.例子中多次创建和Dispose了DataReceiver和DataAnalyzer对象,但由于忘记调用DataAnalyzer的Stop方法,导致产生句柄泄露.本文假定我们已经发现了泄露现象但还不知道原因,讨论如何在这种情况下分析问题. 一.发现问题 在程序运行约一个小时以后,通过任务管理器发现句柄数超过5000,线程数也超过1000.对于一段只需要并行接收和分析数据的简易代码来说,这

句柄泄露实例分析

句柄泄露实例分析 在上篇文章.NET对象与Windows句柄(二):句柄分类和.NET句柄泄露的例子中,我们有一个句柄泄露的例子.例子中多次创建和Dispose了DataReceiver和DataAnalyzer对象,但由于忘记调用DataAnalyzer的Stop方法,导致产生句柄泄露.本文假定我们已经发现了泄露现象但还不知道原因,讨论如何在这种情况下分析问题. 一.发现问题 在程序运行约一个小时以后,通过任务管理器发现句柄数超过5000,线程数也超过1000.对于一段只需要并行接收和分析数据

.NET对象与Windows句柄(二):句柄分类和.NET句柄泄露的例子

上一篇文章介绍了句柄的基本概念,也描述了C#中创建文件句柄的过程.我们已经知道句柄代表Windows内部对象,文件对象就是其中一种,但显然系统中还有更多其它类型的对象.本文将简单介绍Windows对象的分类. 句柄可以代表的Windows对象分为三类,内核对象(Kernel Object).用户对象(GDI Object)和GDI对象,上一篇文章中任务管理器中的“句柄数”.“用户对象”和“GDI对象”计数就是与这几类对象对应的.为什么要这样分类呢?原因就在于这几类对象对于操作系统而言有不同的作用

23、生鲜电商平台-服务器部署设计与架构

补充说明:Java开源生鲜电商平台-服务器部署设计与架构,指的是通过服务器正式上线整个项目,进行正式的运营. 回顾整个章节,我们涉及到以下几个方面: 1. 买家端 2. 卖家端. 3. 销售端 4. 配送端. 5.系统运营端. 6.公司网址 目前根据业务的情况,采购了阿里云服务器,由于是创业,我身上没多少钱,只采购了一台阿里云.(具体配置如下与域名规划如下) 公司网址: http://www.netcai.com 买家端:  http://buyer.netcai.com 卖家端:  http:

ceph集群报 Monitor clock skew detected 错误问题排查,解决

ceph集群报 Monitor clock skew detected 错误问题排查,解决           告警信息如下: [[email protected] ceph]# ceph -w    cluster ddc1b10b-6d1a-4ef9-8a01-d561512f3c1d     health HEALTH_WARN            clock skew detected on mon.ceph-100-81, mon.ceph-100-82            Mon

服务器被攻击了,有什么办法解决吗?

作为一个网络安全运维人员需要做到维护好系统的安全,修复已知的系统漏洞等,同时在服务器遭受攻击时需要迅速的处理攻击,最大限度降低攻击对网络造成的影响.网络攻击是指用户利用网络存在的漏洞和安全缺陷进而对网络中的硬件.软件及数据进行的攻击. 网络攻击有很多种,网络上常用的攻击有DDOS攻击.SYN攻击.ARP攻击以及木马.病毒等等,再安全的服务器也避免不了网络的攻击.作为一个网络安全运维人员需要做到维护好系统的安全,修复已知的系统漏洞等,同时在服务器遭受攻击时需要迅速的处理攻击,最大限度降低攻击对网络