Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles
The goal of the ADO.NET Data Services Framework is to create a simple REST-based framework for exposing and consuming data-centric services easily.

By Elisa Flasko and Mike Flasko (August 2008)
We introduce you to the EDI functionality within BizTalk Server 2006 R2, illustrating schema creation, document mapping, EDI delivery and transmission, and exception handling.

By Mark Beckner (August 2008)
In this excerpt from his upcoming book, Laurence Moroney explains the basics of Silverlight animation and the animation tools available in Expression Blend.

By Lawrence Moroney (August 2008)
We build a Silverlight 2.0 application using the InkPresenter to let users annotate a pre-defined collection of images, perform handwriting recognition, and save the annotations and recognized text into a server-side database.

By Julia Lerman (August 2008)
More ...
Articles by this Author
Bloated view state can be a real performance bottleneck for your Web app, but it can be difficult to diagnose. John Robbins creates a handy tool that records and reports the view state size for pages in your ASP.NET applications.

By John Robbins (November 2007)
Windows Vista has a new API called Wait Chain Traversal (WCT), which allows you to determine when and why a process is deadlocked. Read on.

By John Robbins (July 2007)


By John Robbins (March 2007)
This installment of Bugslayer covers the use of ADPlus to create a minidump of your Microsoft .NET Framework 2.0 pro¬cesses on specific exceptions.

By John Robbins (November 2006)
The latest releases of WinDBG and Visual Studio know exactly how to use source server, so its benefits are available to both .NET and native C++ developers. See why this is so important in tracking down bugs.

By John Robbins (August 2006)
Visual Studio 2005 brought so many new features to the table that it can seem almost overwhelming. One of the most exciting additions is the new unit testing features found in the Test menu on the main menu bar.

By John Robbins (March 2006)
Those of you who have been reading this old Bugslayer column over the last nine years have branded into your frontal lobe a single word: ASSERT! Anytime you can have the code tell you about a problem instead of having to find it by slaving away with a debugger is a huge timesaver.

By John Robbins (November 2005)
By now, you've certainly heard about the big changes coming in Visual Studio® 2005, but when it's time to move your code over it will be the small things that trip you up. In this column, I want to cover two of the many excellent changes that you could easily overlook as you make the move to the new runtime and development tools.

By John Robbins (July 2005)
More ...
Popular Articles
Performance problems can creep into your Web app as it scales up, and when they do, you need to find the causes and the best strategies to address them.

By Richard Campbell and Kent Alstad (April 2008)
Howard Dierking talks to the inventor of C++, Bjarne Stroustrup, about language zealots, the evolution of programming, and what’s in the future of programming.

By Howard Dierking (April 2008)
One-time passwords offer solutions to dictionary attacks, phishing, interception, and lots of other security breaches. Here's how it all works.

By Dan Griffin (May 2008)
Here the author introduces SQL Server Data Services, which exposes its functionality over standard Web service interfaces.

By David Robinson (July 2008)
More ...
Read the Blog
One of the neat things about XAML is that you can not only declare your objects using an XML syntax, but that you can define transformations to rotate, move, and skew your objects. In the August 2008 issue of MSDN Magazine, in an article adapted from his upcoming book Introducing Microsoft Silverlight ...
Read more!
Microsoft has a long history of introducing new features to shipped products, often under the banner of Power Toys or Power Tools. In the August 2008 issue of MSDN Magazine, Brian Randell takes you on a tour of some useful tools for ...
Read more!
Designing software is often an exercise in managing complexity. You can take steps to limit the complexity of any given class by only assigning it a discrete set of responsibilities, applying a concept known as object role stereotypes. In the August 2008 issue of MSDN Magazine, Jeremy Miller explains ...
Read more!
When you evaluate any new technology, pattern, or strategy, you have to consider how that new piece of the puzzle is going to mesh with your existing application architecture. With the Entity Framework, integration is not a problem. In the July 2008 issue of MSDN Magazine, John Papa demonstrated ...
Read more!
Electronic Document Interchange (EDI) encompasses the largest share of real-world business-to-business commerce—nearly 90 percent of the current market—and is growing rapidly year over year. In the August 2008 issue of MSDN Magazine, Mark Beckner introduces ...
Read more!
Separation of presentation and data is not a new idea, but with the growing popularity of technologies such as AJAX and Silver­light, it has become much more prevalent. ADO.NET Data Services Framework began as a way to help developers looking to expose and consume data via services from their applications.. In the August 2008 issue of MSDN ...
Read more!
More ...
Bugslayer
Mini Dump Snapshots and the New SOS
John Robbins

Code download available at: Bugslayer0503.exe (126 KB)
Browse the Code Online
In debugging some large Microsoft® .NET Framework-based ap-plications over the last few months, I've been spending more time looking at mini dumps than at live processes. This is mainly because in those large applications problems surface when the apps are running in production and not on test systems. Because these mini dumps are so important, I've been surprised that many developers don't know how to create them.
In this Bugslayer installment, I will discuss the steps and tools necessary to snap mini dumps for .NET-based applications so you can debug them with the wonderful new Son of Strike (SOS) WinDBG extension DLL. With mini dumps of your .NET processes, you'll finally be able to stand a fighting chance at debugging those production-only problems.
I'll start out by discussing very briefly the type of mini dumps you'll need along with the appropriate tools. For most of the column, I'll show you the exact settings I use to get the proper mini dumps and some techniques for production mini dump snapping. Later I'll discuss some of the new features in the latest SOS Microsoft has released. I previously wrote about SOS (Bugslayer: SOS: It's Not Just an ABBA Song Anymore), but some of the new features can make tracking down tough .NET memory problems a breeze.

Mini Dump Theory and Tools
One thing that you may find confusing about mini dump snapshots is that their file size can be quite large. That's because SOS needs all the virtual memory pages marked as committed in order to do any of its magic. For a simple "Hello World" Windows® Forms application, the resulting mini dump is approximately 30MB. With ASP.NET applications, you're going to see mini dump sizes that range from 300MB to well over 1GB. While you can ask the end user to e-mail you the mini dumps, that will probably make their e-mail administrators and yours want to take mini dumps of both of you as well. At the very least, if you are going to transfer mini dump files around, compressing them with a tool like WinZip can reduce the file size by around 75 percent. Note that with the .NET Framework 2.0, you'll have the option of taking a smaller mini dump (on the order of a few hundred KB) which will allow you to use a subset of SOS commands, such as obtaining a stack trace. Some commands (like the ones related to garbage collection) will still require all committed pages, however.
For your production .NET-based applications, the best way to create mini dumps is with the old standby, ADPlus, formerly named Autodump+. The Debugging Tools for Windows package, freely downloadable at Debugging Tools for Windows, is the home for the latest version. For this column, I'll be using the October 2004 beta release 6.4.4.4 of the Debugging Tools for Windows. Every few months, there's a new release, so you should check back frequently to get the latest. (As an aside, if you are actively debugging with WinDBG or CDB/NTSD, you'll use the ".dump /ma <file>" command so that you can write an appropriate mini dump.)
ADPlus is actually a 5,000-line VBScript application that drives CDB, the console-based debugging UI on top of DBGENG.DLL. (By the way, CDB, NTSD, and WinDBG, are all different UIs on top of DBGENG.DLL so any commands I mention using one of the debuggers will work in all of the debuggers.) When you execute ADPlus, it's building up a script of debugger commands and pumping them into CDB, which does all the heavy lifting. For those of you who used ADPlus in the past, it was relatively nasty because you had to change values inside the actual VBScript file itself. Now ADPlus uses configuration files, in the ubiquitous XML format, to handle all the settings. That makes it much easier to use.
One of the big problems in production environments is that administrators get very nervous when you say you are going to install something on the server. The great news with ADPlus and its supporting files is that a simple XCOPY deployment works great. Just install the Debugging Tools for Windows on your development machine, as you'll need WinDBG to analyze the mini dumps, and then copy the installation directory to the server.
Since ADPlus uses VBScript, you'll need to have Windows Script Host (WSH) version 5.6 or later on the target machine. Run "CSCRIPT /?" at an MS-DOS® prompt to check the version installed. You can download the latest WSH at Microsoft Windows Script Downloads. Another item you'll want to change is the default script host. You should use CSCRIPT.EXE instead of WSCRIPT.EXE so that output will go to Command windows instead of to message boxes, which can hang ADPlus until you click OK. Run "CSCRIPT /H:CScript" and you'll be all set.
In ADPlus, and the Debugging Tools for Windows overall, the documentation in DEBUGGER.CHM is outstanding. You definitely need to read through everything in there to get a good handle on how to run ADPlus as well as how to use the debugging tools. Make sure to concentrate on the Debugging Tools for Windows\Extra Tools\ADPlus in and Debugging Tools for Windows\Debugging Techniques. With the background out of the way, let's turn to actually using ADPlus.

ADPlus Usage
ADPlus has two usage modes: hang and crash. Hang mode is a bit of a misnomer; it really should be called "snap" because ADPlus instructs CDB to attach noninvasively to a process or processes, write out a mini dump, and detach. A noninvasive attach suspends the process and does not actually run under a debug loop so it works on all operating systems from Windows NT® 4.0 and above. If you're familiar with the old USERDUMP.EXE program, ADPlus is the complete replacement for it.
Crash mode, on the other hand, actually attaches the CDB debugger with a native debug loop so you can have the debugger respond to exceptions and even set breakpoints. For example, if you have a case where the ASP.NET worker process is shutting down unexpectedly, you can attach ADPlus in crash mode and have it set a breakpoint on KERNEL32.DLL's ExitProcess. When that breakpoint trips, you can write out a mini dump so you can walk the stack to see what started the process termination.
For most of your debugging, you'll be using ADPlus in hang mode so you can capture dumps at various intervals to see what's going on. While you can specify command-line options to ADPlus to handle all the work, I much prefer to use configuration files. That way I can get even more control over ADPlus and more information into the output.
Figure 1 shows the hang mode configuration file I like to use with .NET-based applications. The comments in the file indicate exactly what each option does and what commands I have selected to run. If you've ever played with WinDBG, you'll see that all the commands are familiar.
To specify the configuration file on the ADPlus command line, use the –c option. Keep in mind that you'll need to specify the complete path to the configuration file if it is in any directory other than the same one containing ADPLUS.VBS. In addition to –c, you'll also need to specify the –o and –pn (or –p).
The output directory, set with the –o, tells ADPlus where to put the output. Each time ADPlus runs, it will create a directory in the output location with the format "Hang_Mode__<date>__Time__ <time>." In that directory, it will create the dump file, the log of the entire CDB output, and a file containing the running processes on the machine. Because ADPlus ensures a unique file name every time, you can run ADPlus repeatedly with the same command-line option and not lose previous runs.
The –pn option specifies the process name you want to attach and dump. For example, if you are using IIS 5.0, you'd specify "-p ASPNET_WP.EXE" to grab your ASP.NET dumps. For IIS 6.0, you'd specify "-p W3WP.EXE". By specifying an actual process name, if there are multiple copies of that process running, ADPlus will dump all of those processes. If you want to identify only a single process, you can do so by using the –p option, which will look for the process ID.
In the case of IIS 6.0, if you want to only snap a mini dump of a particular application pool, the command "TLIST.EXE –v" will show you all running processes and their command lines. (TLIST.EXE comes as part of the Debugging Tools for Windows.) Look through the list for the different W3WP.EXE instances and their –ap command-line options to identify the application pool in which each instance is running.
The majority of my mini dump creation has been performed with the hang mode option to ADPlus. The one problem is that you have to keep manually running the same command line repeatedly to get the runs over a period of time. I have included in this month's source code distribution a program called SpawnRepeatedly that I've used to automate the task of running ADPlus over longer periods of time. You can download it from the MSDN®Magazine Web site.
There's nothing too exciting about the program itself, but I've found it very useful to run on production systems and to snap a mini dump every couple of hours. Keep in mind that the ASP.NET worker process, or any process you attach ADPlus to in hang mode, suspends the process and could possibly cause problems. In most cases, the mini dump snap should take less than a minute, but for some servers, even that could cause problems so you may want to perform some test mini dumps first to gauge the impact.
Note that the configuration file shown in Figure 1 includes actions for some things that you can do later when analyzing the dumps. If you want to minimize the time you stop the application for those occasions where time is an issue, one alternative is to use a very lean configuration file, such as one where the only option used is Clear and where the only action used is FullDump.
The second mode for running ADPlus is directed at telling ADPlus to perform some operations when the process crashes. While in hang mode the debugger is simply suspending the process; in crash mode the debugger attaches using the Win32® native debugging API. Because of the excellent scriptability of the debugging engine, this gives you the opportunity to respond to specific exceptions, conditions, or when certain functions execute.
For example, the configuration file shown in Figure 2 snaps a mini dump whenever a first-chance exception occurs. Since .NET exceptions are implemented internally with Structured Exception Handling (SEH), each time an exception is thrown in your application, you'll have the exact dump that tells you where the exception occurs. I don't run this configuration on production systems because it can slow down the application too much, but it's invaluable in testing. Be aware that this configuration will take up a huge amount of disk space. While .NET makes exceptions much more palatable than they were in Win32, they are truly for exceptional conditions and you should not be seeing them thrown frequently in your normal operation.
Another crash mode configuration that's quite useful is telling ADPlus to snap a mini dump when a process calls ExitProcess. With ASP.NET, this configuration can help you determine why the worker process is jumping out of memory, which is probably the sign of some sort of COM Interop problem. The trick is to tell ADPlus to set the breakpoint on KERNEL32.DLL's ExitProcess and to do a mini dump with full heap at that point.
Figure 3 shows the ExitProcess configuration. By default, ADPlus wants to write out a mini dump on each and every first-chance exception (the moment of the throw). Figure 3 shows how to turn first-chance exception logging off.
With dump creation under your belt, I want to show how you can take advantage of some of the new SOS features to get at that hard-to-find information.

What's New in SOS
If you read my previous column on SOS, you probably saw that SOS is good at dumping out information, but you have to spend your time manually grinding across it to find the really useful sections. The latest SOS, which is now part of WinDBG, makes finding key information, such as all the objects in the Generation 2 heap, trivial. Having spent far too many hours grinding through dumped output and manually trying to find what's in what generation, I'm thrilled to have these new capabilities.
The .NET Framework has the old copy of SOS, so to load the new SOS, you'll execute the ".load clr10\sos" command. The new version is targeted at common language runtime (CLR) 1.0 and 1.1 development. If you are playing with CLR 2.0, you'll want to load the SOS version that comes with the Framework.
The first thing you need to look at is the "!help" command because it looks like all the parameters to the information commands are now documented. You will also see that there are new commands specific to ASP.NET such as "!DumpASPNETCache" (also callable with the shortened "!dac") that will dump out all the data that is in the ASP.NET cache. Since the cache is a place where you are probably holding onto objects too long, being able to see the cache in one command is a huge improvement.
The command that's gotten the most attention is the one that's the most useful, "!DumpHeap" (also shortened to "!dh"). Not only is it now able to tell you which generation an object is in, but the most noticeable improvement is that it's many orders of magnitude faster. To see the statistics of all objects in the Generation 2 heap, the magic command is "!dh –stat –gen 2". That will produce comprehensive output like that shown in Figure 4, so you can see at a glance exactly what's sticking around too long. If you want to see the individual objects, remove the –stat argument and "!dh" dumps the actual objects themselves.
One undocumented feature of the "!dh" command is that you can easily look at the large object heap as well. In looking at a lot of output, I noticed some values listed as coming from Generation 3. Because the .NET garbage collector, at least according to everything I read, only has the three generations (0, 1, and 2), I was a little confused. Thinking it may be the large object heap, I manually dumped the large object heap and compared values. Sure enough, that's what I saw. To see the objects in the large object heap, use 3 as the generation like this: "!dh –stat –gen 3".
Another nifty new trick with "!dh" is the ability to specify a partial type string to search for. If you want to see just the statistics for Generation 2 on objects that have Security in the name, the command is: "!dh –stat –gen 2 –type Security". The new type option makes looking for your own objects trivial. If you haven't guessed this by now, you can mix and match command-line options to "!dh" all you want to see the heap in any way you want to slice and dice it. Finally, "!dh" works great on live debugging in addition to all those memory dumps you're about to create.
Following "!dh", the next most-used command, "!DumpObj" (also shortened to "!do"), has gotten a features boost as well. For those of you who have carpel tunnel syndrome from manually walking down object reference chains, the new –r # (recurse) switch will be much appreciated. If you want to look at an object and what it references, specify a number of objects you want to walk down and "!do" will take care of the rest. While it's a great feature, "!do" does not skip null/Nothing values. Instead, it tries to dump those objects to output, so you may see some errors in the minidump. If you see an error "Could not dump object, error returned was: 0x8007012b" just take a look at the previous CLASS value and you'll see that it is probably null/Nothing.
One of the previous biggest weaknesses of SOS was that it was impossible to look at an array. The new –v switch to "!do" now makes it trivial. Figure 5 shows a simple string array output. I've noticed that the –v switch will only dump out actual reference objects and will not display arrays with value elements.
In addition to poor array handling, in the past SOS also had problems with collections, unless you had a lot of time to manually dump them with "!do". The new "!DumpCollection" (short version: "!dc") will display any collection that's derived from the ICollection interface, which means nearly everything. In the 6.4.4.4 beta release of WinDBG, the "!dc" command is not working too well, but it will be fixed in the final release.
One extremely tough problem to track down in mixed-mode applications is a GCHandle leak. The System.Runtime.InteropServices.GCHandle structure is what's used to hold onto a piece of managed memory that's passed to native code. For the most part, Interop works like a dream, but there are times when the native code no longer references the memory, and the managed side wasn't notified. At such times you have this GCHandle structure keeping your managed objects alive, and it will never be freed. This is especially nasty in the case of pinned memory since the garbage collector will have to move everything else around that location. As you can surmise, the coordination between your managed and native sides is extremely important.
To keep an eye on the GCHandle structures in use, the new "!gchandles" command reports the handle statistics and those managed objects which are being held in the GCHandles table. An example output of the command is in Figure 6. The important numbers are the Strong and Pinned Handles. Strong handles mean the memory is referenced and cannot be garbage collected. Pinned means the object is referenced and is locked in memory. Keep in mind that strong and pinned memory happens to parameters implicitly when you make COM and P/Invoke calls. You'll want to keep an eye on those two numbers and if you see them creeping up, you've got a problem.
In addition to "!GCHandles", the new "!GCHandleLeaks" will help you track down those leaks. "!GCHandleLeaks" works by looking at the handle values in the GCHandle table and scanning all of your process memory looking for references to those objects. If it finds a reference in memory that indicates the memory is still being used, then it's not a leak. If there's no reference to the object the GCHandle structure wraps, the command reports it as a leak. There's a small possibility that there could be false positive results if the native code is holding the managed pointer in a nonstandard way such as a mask value.
The end of the "!GCHandleLeaks" output will show the handles that it believes are leaked. Those values are the actual GCHandle structures. If you take a look at the GCHandle structure with Lutz Roeder's .NET Reflector, you'll see that the structure only contains an int value. To see the actual managed object leaked, perform a debugger DD (dump DWORD) command on the value that was reported leaked; that will show the object address so you can execute the "!do" command to see it.
Another new command, "!DumpAllExceptions" (also shortened to "!dae"), can be used whenever you want to see any exceptions that are still in the GC Heap.
The final new command I want to mention is the awesome "!SaveModule" command. If you're in a situation where you're debugging (either live or a mini dump), and you need to see the source code for a module, it can sometimes be difficult. However, for a managed module, you can pass the load address of the assembly and an output name to the "!SaveModule" like this: "!SaveModule 00400000 temp.exe". That will write out the complete assembly to disk so you can use Reflector to decompile the binary! Why suffer through trying to find the right version of the source code when you've got the actual source right here?

Wrap-Up
In this column, I hope I've given you some of the tips and tricks of gathering the best mini dumps possible in a production environment. You have the ADPlus configuration files I use when debugging so you can use them as a base to start building the custom configurations you'll need for your applications. While the ADPlus documentation is quite good, I strongly recommend that you look at the actual ADPlus source code so you can figure out exactly what will happen with various options.
Finally, I'm sure you're going to love the new SOS. The fact that you can easily see the objects in a specific generation makes it massively more useful that it used to be. While it's still not as easy as debugging in the Visual Studio® .NET debugger, it is the only tool I consider for tackling those nasty production-only problems.

Tips
Tip 67 Since I'm a tools kind of guy, I would be remiss if I also didn't plug Jonathan de Halleux's outstanding MBUnit. It's fully compatible with NUnit, but offers advanced features for creating great tests such as testing against different cultures, data driven testing, and process testing. MBUnit is replacing NUnit for me.
Tip 68 While MBUnit is excellent, the other testing tool you need is from Jamie Cansdale: TestDriven.NET. It's a phenomenal Visual Studio .NET Add-In that allows you to plug in tools like MBUnit, NUnit, and even the upcoming Microsoft Team System into a single one-click testing environment. All I can say is wow!

Send your questions and comments for John to  slayer@microsoft.com.


John Robbins is a cofounder of Wintellect, a software consulting, education, and development firm that specializes in programming for .NET and Windows. His latest book is Debugging Applications for Microsoft .NET and Microsoft Windows (Microsoft Press, 2003). You can contact John at www.wintellect.com.

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.
Page view tracker