What is GDI Object leaks and tips to detect..
Recently I worked for an office issue where Excel 2013 goes to frozen state after executing some time consuming VBA code/macro. It did some operations like – copy ranges and pasted over another sheet within the same workbook. The copy and paste operation iterates over some 100 thousand times depends on the data row etc. It took nearly 3-4 hours to complete the whole copy operation due to data density spreads to x columns with x number of rows.
Problem identification: We saw the application was very much alive but could not able to click or respond to our mouse events like maximize/minimize. Moreover it was slowing the system performance as well. We could not able to figure out the cause in the initial stage. But we tried tools like Procmon, windbg dumps, VMMAP etc could not give that heads up. But after checking the task manager GDI count, we come to know that this is sort of object leak – GDI Leaks creating this hang state/lock situation.
How to identify the GDI object leaks? It is so simple to check such leaks from the task manager itself. Launch the taskmanager > details tab > right click any of the existing column > then ‘Select Columns” enable GDI Object to get added to the details process grid. From there you can keep a note of the count to conclude whether its a GDI leak or not. Typically, you would find this count in hundreds, but in case if you notice them in thousands and also incremented, then something sure to do with GDI leak fix.
What is GDI Objects? According to this MSDN article – GDI Objects are resources that are managed by GDI32.DLL on behalf of an application. Some of the common GDI Objects we consume directly/indirectly through code – Device Contexts (DCs), Bitmaps, Brushes, Fonts, Metafiles, Pens, and Regions etc. These objects gets created using API call but when never gets destructed after usage – this would lead to this leak situation. As like in .NET, it is recommended to dispose of when not interested with that ready to cleaned objects. Of-course, we do this very judiciously, but at times when our code path not cleaned after some exception or some condition branching stops us to do so, then this would be a show stopper for sure :).
What is the limit? It is limited to 64,536 (64k) GDI handles per user session- across all process. But for any individual process, the upper limit is 10000. System allows us to create these many handles and then halts after reaching this limit. You could also try tweaking this limit from registry, but generally not advised to do so due to various reasons like -affects other application performance etc.
What happens after reaching this 10,000 limit? The application would be alive as I said earlier but of no use. It is starving to create further GDI Objects to render it but indefinite halt after that due to no more Create handles permitted. When an application goes out of resources, then the create API call to functions like CreateFont, CreateDC etc would fail with this error : ERROR_INVALID_HANDLE.
There are some tools and guidance to research more on this, but I see very limited materials around this in net. I suggest the below links.
Very old cached MSDN article(thanks to google cache) http://webcache.googleusercontent.com/search?q=cache:XOnUN-jJpGoJ:msdn.microsoft.com/magazine/efea0849-057a-42b7-a5bf-a106bd38faa2&hl=en&gl=in&strip=0&vwsrc=0
Debugging a GDI Resource Leak
http://blogs.msdn.com/b/dsui_team/archive/2013/04/23/debugging-a-gdi-resource-leak.aspx
Suggested to try these Office June updates in case of such leaks
https://support.microsoft.com/en-us/kb/2817579 (enhances copy paste operation speed)
https://support.microsoft.com/en-us/kb/3054794 (some fixes around object leaks)
Update : 19-July
From scott blog, I found this nice tool to see the GDI count under types – http://www.nirsoft.net/utils/gdi_handles.html
How to debug an unmanaged exe under Windbg
Assume that we have got an exe(unmanaged/managed) which is crashing/hang/wanted to debug and see the intermediate values etc. For this example, I have used the below simple cpp program compiled to exe.
Steps for debugging this complied exe in Windbg:
1) Launch Windbg, -> Open Executable, browse and select our cpp program output “ConsoleApplication1.exe”
2) Now set the symbol path and source path pointing to its corresponding directory.
3) Reload the symbol to make sure the relevant symbols loaded.
4) If you press “g” mean go/F5 would run the program and displays the output.
5) Let us put some breakpoints at Main method and also Swap2Numbers to step in line by line debugging.
>bp ConsoleApplication1!main
>bp ConsoleApplication1!Swap2numbers
6) Since we have mapped the source code path also, now on typing “t” would execute/step in line by line. You would also notice the source code window opened up and breakpoint indicator set.
7) If you wanted to unassemble, then use> uf ConsoleApplication1!main (assembly code).
8) When you go line by line debugging, you can view the intermediate value of the function by typing >dv (display variable)
WPF and IE Memory leak -tools & links
Worth mentioning –
2) Internet Explorer client side memory leak detector /tool -> IE Sieve – http://home.wanadoo.nl/jsrosman/
3) WPF progress bar memory leak-
<ProgressBar Name=”Progress” Width=”250″ Height=”15″ Minimum=”0″ Maximum=”1″ Margin=”10″ IsIndeterminate=”True”>
</ProgressBar>
4) Tracking down managed memory leaks (how to find a GC leak) —> http://blogs.msdn.com/b/ricom/archive/2004/12/10/279612.aspx
5) What do the Task Manager memory columns mean? http://windows.microsoft.com/en-US/windows-vista/What-do-the-Task-Manager-memory-columns-mean
Generating memory dump using DebugDiag 1.2 in steps
DebugDiag 1.2
—————–
1. On a computer demonstrating the problem, install DebugDiag 1.2 from http://www.microsoft.com/download/en/details.aspx?id=26798 and accept the default options for installation.
2. Select Start->Programs->Debug Diagnostics Tool 1.2->DebugDiag 1.2.
3. When DebugDiag starts, it should display a wizard to create a rule. If it does not show this, then click the Add Rule button on the Rules tab.
4. Select “Crash”.
5. Click Next and select “A specific process” and click Next.
6. Enter the process name of your application, ie “NotePad.exe” (or whatever the name is, without full path), in the Selected Process text box and click Next.
7. For “Unconfigured First Chance Exceptions”, set Action Type to “Log Stack Trace” with “Action Limit” to 0. Then click Next.
8. Please note the user dump path and click Next.
9. Select “Activate the rule now” and click Finish.
10. Open the Tools menu -> Preferences -> Select the “Enable raw debugger logs. Include debugger output and Engine messages”.
11. At this point, have the users run the application and try to reproduce the issue.
12. When the issue reproduces, it will generate a memory dump to the folder from step
8. Zip up the Logs folder (by default C:\Program Files\DebugDiag\Logs)
9. Analyse it.
DebugDiag 2.0 is out..
DebugDiag 2.0 comes now with the new analysis engine fully converted to .NET to allow for faster analysis rule development. New features > Collection and Analysis modules such as .NET 4.5 support, CLRMD integration, C# and XAML sample rules,Detailed 1st chance exception logging.
Download from here> http://www.microsoft.com/en-us/download/details.aspx?id=40336
Note: I personally used DD and felt really useful for quicker dump analysis instead windbg way of getting out.
About Glowcode
GlowCode is a complete real-time performance and memory profiler for Windows and .NET programmers who develop applications with C++, C#, or any .NET Framework-compliant language. GlowCode helps programmers optimize application performance, with tools to detect memory leaks and resource flaws, isolate performance bottlenecks, profile and tune code, trace real-time program execution, ensure code coverage, isolate boxing errors, identify excessive memory usage, and find hyperactive and loitering objects. For native, managed, and mixed code.
We have used it in our development project and seems useful.
-
Recent
- The ID token is not yet valid. Make sure your computer’s time and time zone are both correct. Current epoch = 1689517128
- .NET Core – How to create a .NET GUI app which runs across the platform
- AKS 2022 updates
- Linux firewall and connectivity issues
- Microsoft Ignite (Sep22-24) event recap & On-demand sessions
- [Linux] Steps to install and configure sysstat package for monitoring.
- Azure Security Enablement – Centralized place for all the links
- Presenting tech session with stories [linkedin learning notes]
- gRPC using .NET core notes
- .NET in 2020 (Build recap)
- #KubeCon CNCF – North America 2019 watchlist
- AKS CLI Sheetcheat for the labs
-
Links
You must be logged in to post a comment.