Diagnosing RegisterWindowsMessage leak

百般思念 提交于 2019-12-11 06:06:42

问题


We are seeing atom pool resource exhaustion on production servers of one of our applications.

Using the fantastic AtomTableMonitor tool, we've isolated the issue to creation of a huge number of atoms by the RegisterWindowsMessage call. They all have names like this:

ControlOfs030D000000000270

where the number at the end changes.

My question is: How do we figure out which process is creating these atoms?

some potential resources:

https://blogs.msdn.microsoft.com/ntdebugging/2012/01/31/identifying-global-atom-table-leaks/


回答1:


Atoms that begin with "ControlOfs..." are created by Borland/Embarcadero's VCL (Visual Component Library) framework in Delphi/C++Builder. These atoms are actually in the form of "ControlOfs<HInstance><ThreadID>", where <HInstance> and <ThreadID> are in hex format (so, in your case, HInstance = 0x030D0000 = 51183616, ThreadID = 0x00000270 = 624).

There is also another atom name that is created by the VCL, in the form of "Delphi<ProcessID>", where <ProcessID> is in hex format.

This means that every instance of an app that uses the VCL creates a new unique "Delphi..." atom, and its main UI thread creates a new unique "ControlOfs..." atom (these atoms are used to store TWinControl object pointers in VCL-created HWNDs via SetProp(), for use by the VCL's FindControl() and IsDelphiHandle() utility functions). Both atoms are registered with GlobalAddAtom() at app startup, and unregistered at app shutdown with GlobalDeleteAtom(), so there is no leak.

However, in Delphi/C++Builder 6 all the way up to RADStudio XE2, there is yet another atom that uses the same "ControlOfs..." name. This atom is created with RegisterWindowMessage() (for a private RM_GetObjectInstance window message), which cannot be unregistered. So, every time an affected VCL app is run, this unique atom is created and subsequently leaked.

This was eventually fixed by Embarcadero in RADStudio XE3 in 2012 (Andreas Hausladen posted a patch for earlier VCL versions). But pre-existing apps that are compiled with older versions of the VCL are affected, and there is nothing you can do to stop them from leaking without patching them to use a static name with RegisterWindowMessage().

So, to answer your question, using a combination of AtomTableMonitor and Task Manager, you should be able to figure out which apps you are running are VCL apps, and then you can check them individually for leaking atoms. Or, use SysInternals Process Monitor with a Thread Create filter to get a list of thread IDs and their creating processes over time, then you can match up those thread IDs to the leaked atom names.




回答2:


You can use a tool like API Monitor and set it up to track only RegisterWindowsMessage. It will show you which process is using this function and a stack trace too (though probably not too useful without symbols).

Also, a quick Google search for ControlOfs finds https://forums.embarcadero.com/thread.jspa?threadID=47678 which matches your issue. They say it's a bug in VCL. Someone posted this fix pack if you have the code:

http://andy.jgknet.de/blog/bugfix-units/vclfixpack-10/

If you don't have the code, I suggest you look for Delphi/VCL applications in your production server and try to update them or report the issue.



来源:https://stackoverflow.com/questions/46549319/diagnosing-registerwindowsmessage-leak

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!