2017-09-20 107 views
1

我们正试图解决服务器运行一段时间后服务器启动异常的生产服务器上的一个令人讨厌的问题。诊断Win32 RegisterClass泄漏

诊断程序让我们相信可能存在DLL中的错误,该错误由此服务器上运行的进程之一导致全局原子泄漏。假定的向量是一个调用RegisterClass而没有相应的UnregisterClass的进程(并且类名称使用随机数作为名称的一部分,所以每次进程启动时它都是不同的类名)。

本文提供了一些信息:https://blogs.msdn.microsoft.com/ntdebugging/2012/01/31/identifying-global-atom-table-leaks/

但是大家都不愿意尝试在生产服务器上的内核模式调试,所以我们尝试安装的WinDbg和使用克·原子命令列表原子给定会话!

我使用windbg连接到其中一个会话中的进程(这些进程以Windows服务的形式运行(如果有的话)),然后调用!gatom命令。返回的原子列表中没有任何窗口类。

然后我读此:https://blogs.msdn.microsoft.com/oldnewthing/20150429-00/?p=44984

和听起来有用于窗户类的单独原子表。无法查询它。我希望能够真正看到有多少windows类的原子已经被注册,并且看看这个列表是否随着时间的推移变大,表明泄漏。

关于!gatom的文档很少,我希望能得到一些专家确认或关于如何继续的建议。

有没有人有关于如何获得生产服务器上注册Windows类的列表的任何想法?同一应用程序的

我们运行多个实例(> 50)从孤立的可执行文件和DLL运行单独注册服务 - 所以每个那些:


更多详细询问时,服务器开始胡作非为会发生什么50个实例拥有自己的专用可执行文件和DLL。

在正常运行期间,进程卸载并重新加载DLL(大约每小时)。有一个windows类,它是DLL使用的“会话句柄”的一部分(会话句柄是注册的Windows类名称的一部分),并且每次加载DLL时会话句柄都是唯一的。因此,每个小时都会有一个额外的Window类注册,由DLL(我们的服务保持运行)完成。

经过一段时间后,系统将进入进一步尝试加载有问题的DLL失败的状态。这可能发生在其中一个服务上,然后随着时间的推移,其他服务将开始出现同样的问题。

发生这种情况时,重新启动服务确实不是解决了这个问题。我们发现让事情再次正常运行的唯一方法是重新启动服务器。

我们正在监视内存提交负载,而且我们完全在服务器的虚拟内存中。我们甚至在物理内存大小内。

我只是做了一个代码审查该DLL的供应商,它看起来像他们实际上从DLL本身调用的RegisterClass(他们只能从DLL做一个的RegisterClass调用,它是一个静态的字符串 - 不每个会话的不同类名)。该DLL启动一个EXE,并且该EXE是注册会话特定类名称的EXE。他们的EXE确实调用了UnregisterClass(即使它没有,EXE在我们卸载它们的DLL时被终止,所以看起来这可能不是这样)。

我现在没有子弹了。行为似乎像某种资源泄漏或池耗尽。下次发生这种情况时,我会尝试使用windbg连接到失败的进程,并查看应用程序原子池的外观 - 但我不希望这会发生什么。


更新:优秀的AtomTableMonitor工具已将问题缩小到流氓RegisterWindowMessage。我要问专注于这个确切问题进行更具体的问题:Diagnosing RegisterWindowsMessage leak

+0

*“每次进程启动时都是不同的类名”* - 不是每个进程原子表中存储窗口类原子吗?如果是这种情况,那么对每个进程运行使用不同的类名是没有问题的。 – IInspectable

+0

@IInspectable [RegisterClass](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633586.aspx)docu规定:应用程序注册的所有窗口类在终止时都未注册。 ,然后:'卸载DLL时,没有注册的窗口类未注册。 DLL在卸载时必须明确注销它的类。' – ssbssa

+0

@ssbssa:因此,当进程关闭时,所有的窗口类都是未注册的,而不管注册它们的模块如何。这似乎是一个强烈的迹象,窗口类*存储在每个进程的原子表中。 – IInspectable

回答

1

您可以尝试使用出现此独立global atom monitor
的应用有能力监测,在不同的会话

运行服务
原子

顺便说一句,如果你已经缩小它RegisterWindowMessage 那么窥探++可以登录注册的信息系统广泛随着线程和进程

间谍++(我使用它vs2015社区)

enter image description here

Ctrl + M键系统选择所有Windows

在邮件选项卡

全部清除,然后选择注册

,并开始记录

,你还可以保存日志(尽管是奇怪的扩展,它仍然是纯文本)

powershell -c "gc spy++.sxl -Tail 3" 

<000152> 001F01A4 P message:0xC1B2 [Registered:"nsAppShell:EventID"] wParam:00000000 lParam:06EDFCE0 time:4:2 
7:49.584 point:(408, 221) 
<000153> 001F01A4 P message:0xC1B2 [Registered:"nsAppShell:EventID"] wParam:00000000 lParam:06EDFCE0 time:4:2 
7:49.600 point:(408, 221) 
<000154> 001F01A4 P message:0xC1B2 [Registered:"nsAppShell:EventID"] wParam:00000000 lParam:06EDFCE0 time:4:2 
7:49.600 point:(408, 221)