<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="sv-SE"><title type="html">If broken it is, fix it you should</title><subtitle type="html">Using the powers of the debugger to solve the problems of the world - and a bag of chips&lt;br/&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;I&gt;by Tess Ferrandez, ASP.NET Escalation Engineer (Microsoft)&lt;/I&gt;
</subtitle><id>http://blogs.msdn.com/tess/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/tess/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2009-08-17T12:43:21Z</updated><entry><title>MSDN Radio (Swedish) - Tess Corner</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2010/01/15/msdn-radio-swedish-tess-corner.aspx" /><id>http://blogs.msdn.com/tess/archive/2010/01/15/msdn-radio-swedish-tess-corner.aspx</id><published>2010-01-15T12:04:48Z</published><updated>2010-01-15T12:04:48Z</updated><content type="html">&lt;p&gt;MSDN Radio is a Swedish MSDN podcast that is &lt;a href="http://buzzfrog.blogs.com/"&gt;Dag König&lt;/a&gt; puts together every other week.&amp;#160; The show contains a number of different segments and is usually pretty fun to listen to.&lt;/p&gt;  &lt;p&gt;Starting this week, and hopefully every other week or so during the spring, I will have a 5-15 min segment on the show called Tess Corner where I’ll be talking about current ASP.NET and other .net issues or something special I’m working on.&amp;#160; &lt;/p&gt;  &lt;p&gt;In the first episode posted here &lt;a title="http://channel9.msdn.com/posts/buzzfrog/MSDN-Radio-11-Jan--Tess-Corner/" href="http://channel9.msdn.com/posts/buzzfrog/MSDN-Radio-11-Jan--Tess-Corner/"&gt;http://channel9.msdn.com/posts/buzzfrog/MSDN-Radio-11-Jan--Tess-Corner/&lt;/a&gt; I talk about debugging .NET apps with IntelliTrace in Visual Studio.NET 2010.&lt;/p&gt;  &lt;p&gt;Check out the other MSDN episodes on &lt;a title="http://channel9.msdn.com/tags/MSDN+Radio/" href="http://channel9.msdn.com/tags/MSDN+Radio/"&gt;http://channel9.msdn.com/tags/MSDN+Radio/&lt;/a&gt; (also in Swedish) and if you listen to the show and want to hear about something special, feel free to post me a comment.&lt;/p&gt;  &lt;p&gt;Have a good one&amp;#160; &lt;br /&gt;Tess &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9948899" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry><entry><title>Debugging Native memory leaks with Debug Diag 1.1</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2010/01/14/debugging-native-memory-leaks-with-debug-diag-1-1.aspx" /><id>http://blogs.msdn.com/tess/archive/2010/01/14/debugging-native-memory-leaks-with-debug-diag-1-1.aspx</id><published>2010-01-14T13:21:02Z</published><updated>2010-01-14T13:21:02Z</updated><content type="html">&lt;p&gt;I often get questions about debugging native memory leaks. In other words, cases where you have high memory usage in your application but you can see that .net memory usage is not all that high.&lt;/p&gt;  &lt;p&gt;Recently I was helping out on such a case and this post details both generally how you go about troubleshooting these issues as well as what troubleshooting steps we went through in this particular case.&lt;/p&gt;  &lt;p&gt;Essentially you would go through these steps to troubleshoot a native memory leak:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1. Find out if your memory usage / leak is mostly .net memory or native memory      &lt;br /&gt;2. If it is native memory that is “leaking”, use a tool like debug diag 1.1. to track allocations and deallocations       &lt;br /&gt;3. Look at the main allocators and the stacks associated with the biggest chunks of allocations to determine who is making the allocations and why the memory is not released.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;1. Find out if your memory usage / leak is mostly .net memory or native memory&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;There are various ways to find out if your memory usage is mostly .net or native.&amp;#160; &lt;br /&gt;    &lt;br /&gt;&lt;strong&gt;&lt;em&gt;Using perfmon to determine where your memory is going&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The best way is probably to use performance monitor and collect a log over the lifetime of the process that is leaking with at least the following counters for the specific process (note that _total or _global counters are not very helpful here)&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;.NET CLR Memory/#Bytes in all heaps &lt;/li&gt;    &lt;li&gt;Process/Private Bytes &lt;/li&gt;    &lt;li&gt;Process/Virtual Bytes &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Simplified, Virtual Bytes is the memory that the process reserves, Private Bytes is how much of that the memory that the process actually uses and #Bytes in all Heaps is how much of the Private Bytes goes to memory stored on the .NET GC heap.&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;This is not entirely accurate if you want to be a nitpicker about what Private Bytes really means, but it is accurate enough for the purposes of troubleshooting a memory issue.&lt;/p&gt;  &lt;p&gt;You can create such a logfile by following these steps&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1. Open perfmon (Performance under Administrative Tools)      &lt;br /&gt;2. Under Performance Logs and Alerts, right-click Counter Logs and choose New Log Settings, give it a name and click ok.       &lt;br /&gt;3. Click “Add Counters” and choose the counters above.&amp;#160; The best way to make sure you get the instance counters, rather than _Total and _Global is to choose All instances       &lt;br /&gt;4. Once you have added the counters, fill in the name of an administrator in the Run As: box and fill out the password.&amp;#160; (This is important if you are logging for w3wp.exe for example as some counters are only available when you run the log as an admin)       &lt;br /&gt;5. The counter log will now be running, collecting data (shows up as green in the counter logs view) but you can start and stop it at any time.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Once you have this performance log you can now compare these values and specifically compare the trend and amounts for Private Bytes and #Bytes in all heaps to see if your memory leak is native (non .net) or .net related.&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;If your memory growth/usage is mostly .net, have a look through some of the other posts on debugging memory issues to check into how to troubleshoot them.&lt;/p&gt;  &lt;p&gt;If however # Bytes in all heaps is pretty moderate you should continue reading from step 2 and on.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;Getting memory usage info from a dump file &lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If you got a memory dump of the process but “forgot” to create a perfmon log with the counters described above, you can find out from the memory dump where the memory is used.&lt;/p&gt;  &lt;p&gt;Open the memory dump in Windbg (File/Open Crash Dump) and run the command !address –summary&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Note: The output might differ with different versions of windbg&lt;/p&gt; &lt;/blockquote&gt;  &lt;pre class="debug"&gt;0:000&amp;gt; !address -summary 
-------------------- Usage SUMMARY --------------------------&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;TotSize   (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; KB)&amp;#160;&amp;#160; Pct(Tots) Pct(Busy)&amp;#160;&amp;#160; Usage&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;1bf2f000  (&amp;#160; 457916) : 21.84%&amp;#160;&amp;#160;&amp;#160; 23.18%&amp;#160;&amp;#160;&amp;#160; : RegionUsageIsVAD&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;772b000   (&amp;#160; 122028) : 05.82%&amp;#160;&amp;#160;&amp;#160; 00.00%&amp;#160;&amp;#160;&amp;#160; : RegionUsageFree&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;5881000   (&amp;#160;&amp;#160; 90628) : 04.32%&amp;#160;&amp;#160;&amp;#160; 04.59%&amp;#160;&amp;#160;&amp;#160; : RegionUsageImage&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;22bc000   (&amp;#160;&amp;#160; 35568) : 01.70%&amp;#160;&amp;#160;&amp;#160; 01.80%&amp;#160;&amp;#160;&amp;#160; : RegionUsageStack&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;8b000     (&amp;#160;&amp;#160;&amp;#160;&amp;#160; 556) : 00.03%&amp;#160;&amp;#160;&amp;#160; 00.03%&amp;#160;&amp;#160;&amp;#160; : RegionUsageTeb&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;54dcb000  ( 1390380) : 66.30%&amp;#160;&amp;#160;&amp;#160; 70.40%&amp;#160;&amp;#160;&amp;#160; : RegionUsageHeap&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;0         (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0) : 00.00%&amp;#160;&amp;#160;&amp;#160; 00.00%&amp;#160;&amp;#160;&amp;#160; : RegionUsagePageHeap&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;1000      (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 4) : 00.00%&amp;#160;&amp;#160;&amp;#160; 00.00%&amp;#160;&amp;#160;&amp;#160; : RegionUsagePeb&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;1000      (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 4) : 00.00%&amp;#160;&amp;#160;&amp;#160; 00.00%&amp;#160;&amp;#160;&amp;#160; : RegionUsageProcessParametrs&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;1000      (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 4) : 00.00%&amp;#160;&amp;#160;&amp;#160; 00.00%&amp;#160;&amp;#160;&amp;#160; : RegionUsageEnvironmentBlock&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;   Tot: 7fff0000 (2097088 KB) Busy: 788c5000 (1975060 KB) 
-------------------- Type SUMMARY --------------------------&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;TotSize   (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; KB)&amp;#160;&amp;#160; Pct(Tots)&amp;#160; Usage&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;772b000   (&amp;#160; 122028) : 05.82%&amp;#160;&amp;#160; : &amp;lt;free&amp;gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;5ee5000   (&amp;#160;&amp;#160; 97172) : 04.63%&amp;#160;&amp;#160; : MEM_IMAGE&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;5fb000    (&amp;#160;&amp;#160;&amp;#160; 6124) : 00.29%&amp;#160;&amp;#160; : MEM_MAPPED&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;723e5000  ( 1871764) : 89.26%&amp;#160;&amp;#160; : MEM_PRIVATE &lt;p&gt;&lt;/p&gt;-------------------- State SUMMARY --------------------------
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; TotSize (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; KB)&amp;#160;&amp;#160; Pct(Tots)&amp;#160; Usage
&lt;br /&gt;&amp;#160;&amp;#160; 5a1e4000 ( 1476496) : 70.41%&amp;#160;&amp;#160; : MEM_COMMIT
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 772b000 (&amp;#160; 122028) : 05.82%&amp;#160;&amp;#160; : MEM_FREE
&lt;br /&gt;&amp;#160;&amp;#160; 1e6e1000 (&amp;#160; 498564) : 23.77%&amp;#160;&amp;#160; : MEM_RESERVE &lt;br /&gt;
&lt;p&gt;Largest free region: Base 06b10000 - Size 02170000 (34240 KB)&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;From this we can deduce a couple of things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;MEM_COMMIT&lt;/em&gt;&lt;/strong&gt; is the committed memory, this should be fairly close to &lt;strong&gt;&lt;em&gt;Private Bytes&lt;/em&gt;&lt;/strong&gt;.&amp;#160; In this particular case this process was using almost 1.4 GB of memory 

  &lt;br /&gt;

  &lt;br /&gt;&lt;strong&gt;&lt;em&gt;MEM_RESERVE + MEM_COMMIT&lt;/em&gt; &lt;/strong&gt;is the total reserved bytes, so this is &lt;strong&gt;&lt;em&gt;Virtual Bytes&lt;/em&gt;&lt;/strong&gt; in Perfmon.&amp;#160; Here we can see that the process has reserved about 500 MB more than it committed, i.e. 500 MB more than it actually used.&amp;#160; This is fairly normal for a big process as for example it will reserve chunks of memory for the .NET GC heap that it might not use all of, and there is some overhead reservations for dlls etc. as well as other types of reservations.&lt;/p&gt;

&lt;p&gt;From the &lt;strong&gt;&lt;em&gt;Usage SUMMARY&lt;/em&gt;&lt;/strong&gt; section we can see where the reservations were made. RegionUsageIsVAD for example is allocations made with VirtualAlloc (.NET GC Heap for example goes here).&amp;#160; RegionUsageIsImage is memory used for dlls and executables.&amp;#160; RegionUsageStack is stack space for the threads, and RegionUsageHeap is for allocations on the NT Heaps.&amp;#160;&amp;#160;&amp;#160; In this particular case we can see that most of the reservations (66.3%) and the commits (70.4%) are done on the NT heaps.&amp;#160;&amp;#160;&amp;#160; This is typical for a native leak.&amp;#160; If it was high .NET memory usage we would see a lot of the memory used for RegionUsageIsVAD.&lt;/p&gt;

&lt;p&gt;If you want to learn more about the !address –summary output, check out the help in windbg for the command or check the &lt;a href="http://blogs.msdn.com/tess/archive/2008/02/20/net-debugging-demos-lab-3-memory-review.aspx"&gt;lab 3 review&lt;/a&gt; where I have described some of this in more detail.&lt;/p&gt;

&lt;p&gt;We can also check out exactly how much memory is used for .net objects by loading up sos in windbg (.loadby sos mscorwks) and then run !eeheap –gc.&amp;#160; I have truncated the output below to just show the important parts&lt;/p&gt;

&lt;pre class="debug"&gt;0:000&amp;gt; !eeheap -gc&lt;br /&gt;Number of GC Heaps: 8&lt;br /&gt;------------------------------&lt;br /&gt;…&lt;br /&gt;------------------------------&lt;br /&gt;GC Heap Size&amp;#160;&amp;#160; 0x84680(&lt;strong&gt;542,336&lt;/strong&gt;)&lt;/pre&gt;

&lt;p&gt;In this process we were using an incredibly small amount of .NET object, ~540k, so we can say for sure here that the leak is native.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. If it is native memory that is “leaking”, use a tool like debug diag 1.1. to track allocations and deallocations &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next step in the process is to collect data about the leak and for this we can use&amp;#160; &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&amp;amp;displaylang=en"&gt;Debug Diag 1.1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The download page gives the instructions needed, in order to start monitoring for leaks&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;To debug memory and handle usage, use one of the following: 
    &lt;br /&gt;

    &lt;br /&gt;1. Create a leak rule against the process in question. The leak monitoring feature will track memory allocations inside the process. Tracking is implemented by injecting a DLL (leaktrack.dll) into the specified process and monitoring memory allocations over time. When configuring a memory and handle leak rule, you can specify memory dump generation based on time or memory usage. 

    &lt;br /&gt;2. Using the “processes” view, right-click the process in question and select the “monitor for leaks” option. When the process has grown to the suspected problem size, manually dump the process by right-clicking on the same process in the processes view and choosing the “Create Full Userdump” option.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A few notes about this:&amp;#160; Leak tracking will only record leaks that occur while leak tracking is turned on.&amp;#160; I know this may sound obvious but I am mentioning this because we often get leak track dumps that span only over a small period of time and does not include the allocations, because people have started leaktracking when memory was already high.&lt;/p&gt;

&lt;p&gt;The other thing that is important to note is that by default, leak tracking will start recording stacks 15 minutes after leak tracking begins.&amp;#160; This is to allow for an app to do the initial allocations like build up the cache, start up the form etc. before starting to monitor, so that the tracking only contains the relevant leak info.&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_6.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_thumb_2.png" width="404" height="331" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve found that the best way to get all the info i need is to start up the application and let it initialize things, and then run leak tracking with the checkbox to record call stacks immediately checked.&amp;#160; (This is under tools/options in debug diag)&lt;/p&gt;

&lt;p&gt;When you start Debug Diag you will be greeted with the Select Rule Type and here you choose Memory and Handle Leak and follow the steps above.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_thumb.png" width="404" height="354" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;You can choose to have debug diag automatically generate dumps when the process reaches a certain size, but the easiest is probably to just choose the Memory and Handle Leak rule, and click next next finish, and then right-click on the process in the processes tab once the leak has manifested itself to get a memory dump (as per the original instructions.&lt;/p&gt;

&lt;p&gt;
  &lt;br /&gt;&lt;strong&gt;3. Look at the main allocators and the stacks associated with the biggest chunks of allocations to determine who is making the allocations and why the memory is not released.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ok, so now we have the memory dump containing the information about the leak.&amp;#160; The cool thing here is that Debug Diag has an analysis feature that analyzes the dump for you.&lt;/p&gt;

&lt;p&gt;Under the Advanced Analysis tab in Debug Diag, select the MemoryAnalysis.asp script and click add data files to add your memory dump, then click on “Start Analysis”.&lt;/p&gt;

&lt;p&gt;This will generate a report that will pop up in your browser showing you information about all the allocations etc.&lt;/p&gt;

&lt;p&gt;The first part of the report is an analysis summary showing a list of the components that allocated the most memory (and didn’t release them).&amp;#160; In this case rsaenh.dll allocated 703 MB so we probably don’t even have to worry about the advapi32.dll allocations.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_thumb_3.png" width="1104" height="132" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you happen to debug a dump where most of the memory is .net you will probably see mscorwks.dll as one of the top allocators.&amp;#160; This doesn’t mean that mscorwks.dll is leaking, it just means that the GC allocated a lot of segments that it didn’t release because the .net objects are still in use.&amp;#160; If that is the case you need to follow some of the other articles on how to debug .net memory leaks instead.&lt;/p&gt;

&lt;p&gt;If you don’t see any big allocators in this list, you probably didn’t leak track for long enough.&amp;#160; You can see how long tracking has been turned on, and how much has been allocated during that time by following the Leak Analysis Report a bit further down in the report output.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_thumb_4.png" width="244" height="82" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Going back to the issue at hand, we saw that most allocations were made by rsaenh!ContAlloc+17.&amp;#160; Does that mean that this method leaks?&amp;#160; Not neccessarily… we will have to look at the call stacks leading up to the allocations to see why it doesn’t release the memory.&lt;/p&gt;

&lt;p&gt;If we follow the link for rsaenh!ContAlloc+17 we will see some statistics about the allocations&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_12.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_thumb_5.png" width="804" height="374" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;So from here we find that most of the problematic allocations are the 422 byte allocations since a total of 689 MB was allocated in 422 byte chunks.&lt;/p&gt;

&lt;p&gt;From here we can then drop down and look at the call stacks for the 422 byte allocations and find&lt;/p&gt;

&lt;div class="SampleCode"&gt;
  &lt;p&gt;&lt;b&gt;Call stack sample 4&lt;/b&gt;&lt;/p&gt;

  &lt;p&gt;Address&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0x0e309518
    &lt;br /&gt;Allocation Time&amp;#160;&amp;#160; 00:05:00 since tracking started

    &lt;br /&gt;Allocation Size&amp;#160;&amp;#160; 422 Bytes&lt;/p&gt;

  &lt;p&gt;Function&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Source&amp;#160;&amp;#160; Destination
    &lt;br /&gt;rsaenh!ContAlloc+17&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ntdll!RtlAllocateHeap

    &lt;br /&gt;rsaenh!MakeNewKey+6c&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; rsaenh!ContAlloc

    &lt;br /&gt;rsaenh!CPDeriveKey+3b1&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; rsaenh!MakeNewKey

    &lt;br /&gt;advapi32!CryptDeriveKey+af

    &lt;br /&gt;SomeCryptoComponent+8328&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; advapi32!CryptDeriveKey

    &lt;br /&gt;SomeCryptoComponent+4ef5

    &lt;br /&gt;oleaut32!DispCallFunc+16a

    &lt;br /&gt;oleaut32!CTypeInfo2::Invoke+234&amp;#160;&amp;#160; oleaut32!DispCallFunc

    &lt;br /&gt;. . .&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Note: I have obfuscated the name of the 3rd party component here.&lt;/p&gt;

&lt;p&gt;This call stack tells us that a method in the component “SomeCryptoComponent.dll” is calling advapi32!CryptDeriveKey and this is what eventually leads to the allocations we are seeing.&amp;#160;&amp;#160; We can’t see the method in SomeCryptoComponent.dll because we don’t have the symbols (pdb files) for it, but if we did we could add them to the symbol path under tools/options and rerun the analysis to get a better stack.&lt;/p&gt;

&lt;p&gt;Either way,&amp;#160; whenever you call CryptDeriveKey, you need to pair it up with a CryptDestroyKey when you are done with the Key in order to release memory.&amp;#160; For some reason this is not happening here and thus the memory used for the keys is left allocated and this is what is causing the memory leak here.&lt;/p&gt;

&lt;p&gt;In this particular case, the vendor for the SomeCryptComponent.dll already had an update with a fix ready to go, but I wanted to write this case study to show how you can track down a native memory leak like this with debug diag.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Have a good one,&lt;/p&gt;

&lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9948358" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="Memory issues" scheme="http://blogs.msdn.com/tess/archive/tags/Memory+issues/default.aspx" /><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry><entry><title>High CPU in .NET app using a static Generic.Dictionary</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/12/21/high-cpu-in-net-app-using-a-static-generic-dictionary.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/12/21/high-cpu-in-net-app-using-a-static-generic-dictionary.aspx</id><published>2009-12-21T10:02:20Z</published><updated>2009-12-21T10:02:20Z</updated><content type="html">&lt;p&gt;A couple of weeks ago I helped out on a high CPU issue in an ASP.NET application.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Problem description&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Every so often they started seeing very slow response times and in some cases the app didn’t respond at all and at the same time the w3wp.exe process was sitting at very high CPU usage 80-90%.&amp;#160; This started happening under high load, and to get the application to start responding again they needed to restart IIS.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Debugging the problem&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;They gathered a few memory dumps during the high CPU situation for us to review and when running the sos.dll command ~* e !clrstack (in windbg) to see what all the threads were doing we found that they were all stuck in callstacks similar to this one:&lt;/p&gt;  &lt;pre class="debug"&gt;OS Thread Id: 0x27dc (124) 
  ESP&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; EIP&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;2f77ed24 795b3c5c System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.__Canon, mscorlib]].FindEntry(Int32) 
2f77ed3c 795b3835 System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.__Canon, mscorlib]].ContainsKey(Int32) 
2f77ed40 209f1932 MyComponent.Settings.get_Current() 
... 
SOME STACK FRAMES REMOVED AS THEY ARE NOT IMPORTANT FOR THIS ISSUE 
... 
2f77f0a4 209f7545 ASP.MyApp_default_aspx.ProcessRequest(System.Web.HttpContext) 
2f77f0a8 65fe6bfb System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 
2f77f0dc 65fe3f51 System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef) 
2f77f11c 65fe7733 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception) 
2f77f16c 65fccbfe System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object) 
2f77f188 65fd19c5 System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest) 
2f77f1bc 65fd16b2 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest) 
2f77f1c8 65fcfa6d System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32) 
2f77f3d8 79f047fd [ContextTransitionFrame: 2f77f3d8] 
2f77f40c 79f047fd [GCFrame: 2f77f40c] 
2f77f568 79f047fd [ComMethodFrame: 2f77f568]&lt;/pre&gt;

&lt;p&gt;In other words, the method MyComponent.Settings.get_Current() was calling ContainsKey on a Generic.Dictionary object and for some reason it was getting stuck when trying to find the entry.&lt;/p&gt;

&lt;p&gt;Looking at the MyComponent.Settings.get_Current() method, we found that the Generic.Dictionary it was calling ContainsKey on was a static dictionary and that all threads were working on the same dictionary.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/xfhwa508(VS.80).aspx"&gt;The MSDN documentation about Generic.Dictionary&lt;/a&gt; has the following information about the thread safety of Dictionary objects&amp;#160; &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A &lt;b&gt;Dictionary&lt;/b&gt; can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with write accesses, the collection must be locked during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What is happening here, and causing the high CPU is that the FindEntry method walks through the dictionary, trying to find the key.&amp;#160; If multiple threads are doing this at the same time, especially if the dictionary is modified in the meantime you may end up in an infinite loop in FindEntry causing the high CPU behavior and the process may hang.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resolution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These type of timing issues with static collections are fairly common in ASP.NET apps with high load.&lt;/p&gt;

&lt;p&gt;To resolve this timing issue you should take special care to synchronize (lock) around access to the dictionary if there is a possibility that you may have multiple writers working at the same time or if there is a possibility that you write while someone else is reading/enumerating through the same dictionary.&amp;#160; &lt;/p&gt;

&lt;p&gt;In general, I would recommend to always read the thread safety information carefully when using static collections as many of them require that you implement synchronization on concurrent read/write operations, to avoid this type of issue or issues with for example HashTables where you may get exceptions like InvalidOperationException “Load Factor Too High”. &lt;/p&gt;

&lt;p&gt;Have a good one,&lt;/p&gt;

&lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9939496" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="Performance issues and hangs" scheme="http://blogs.msdn.com/tess/archive/tags/Performance+issues+and+hangs/default.aspx" /><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry><entry><title>Advanced .NET Debugging book</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/12/15/advanced-net-debugging-book.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/12/15/advanced-net-debugging-book.aspx</id><published>2009-12-15T13:43:44Z</published><updated>2009-12-15T13:43:44Z</updated><content type="html">&lt;p&gt;Last week i got the new &lt;a href="http://www.amazon.com/gp/product/0321578899?ie=UTF8&amp;amp;tag=advancenetdeb-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0321578899"&gt;Advanced .NET Debugging&lt;/a&gt; book by Mario Hewardt (co-authored with Daniel Pravat) in the mail.&amp;#160; I had the pleasure of tech reviewing it earlier this year and it is a really good deep dive in .net debugging and .net internals.&lt;/p&gt;  &lt;p&gt;The book talks about debugging .net apps with WinDbg and with &lt;a href="http://blogs.msdn.com/debuggingtoolbox/archive/tags/PowerDbg+Scripts/default.aspx"&gt;PowerDBG&lt;/a&gt; (Powershell scripts for debugging by Roberto Farah) as well as other tools and techniques for debugging .net apps, and is well worth a read if you are interested in .net debugging.&lt;/p&gt;  &lt;p&gt;Enjoy,   &lt;br /&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9937030" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="General debugging tidbits" scheme="http://blogs.msdn.com/tess/archive/tags/General+debugging+tidbits/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry><entry><title>More debugging videos and a Resource List from my TechED and Oredev sessions on debugging asp.net applications</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/11/18/more-debugging-videos-and-a-resource-list-from-my-teched-and-oredev-sessions-on-debugging-asp-net-applications.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/11/18/more-debugging-videos-and-a-resource-list-from-my-teched-and-oredev-sessions-on-debugging-asp-net-applications.aspx</id><published>2009-11-18T15:49:00Z</published><updated>2009-11-18T15:49:00Z</updated><content type="html">&lt;P&gt;I just returned from &lt;A href="http://www.oredev.se/" mce_href="http://www.oredev.se/"&gt;Oredev&lt;/A&gt; and &lt;A href="http://www.microsoft.com/europe/teched/" mce_href="http://www.microsoft.com/europe/teched/"&gt;TechED EMEA&lt;/A&gt;, both conferences were very interesting in their own special ways.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/MoredebuggingvideosandaR.netapplications_EC78/image_2.png" mce_href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/MoredebuggingvideosandaR.netapplications_EC78/image_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px 15px 0px 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image align=left src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/MoredebuggingvideosandaR.netapplications_EC78/image_thumb.png" width=206 height=114 mce_src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/MoredebuggingvideosandaR.netapplications_EC78/image_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;TechED was of course bigger with a lot of good sessions on my specific area while Oredev is a bit more small and cozy, and a way to meet people that deal with completely different things than I do, like JRuby, Clojure, UI Design what have you… and I guess to some extent to get a reality check and see what the world looks like outside of my .net bubble:)&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;STRONG&gt;Windows Crash Dump Analysis with Daniel Pearson&lt;/STRONG&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;In particular I really enjoyed Daniel Pearson’s session on Windows Crash Dump Analysis where he discussed how to debug BSODs (blue-screens). &lt;BR&gt;He said something interesting that really struck a chord with me.&amp;nbsp; “You should be happy when you get a Blue Screen because that is Windows way of protecting you from drivers corrupting data on your system” :)&amp;nbsp; &lt;/P&gt;
&lt;P&gt;A couple of outtakes from this… If you get a BSOD, don’t just dismiss it.&amp;nbsp; It contains a lot of juicy info like stop codes (telling you why it crashed) and oftentimes the driver that made it crash (because 95% of the time it is a driver or problematic hardware causing the problem by trying to do or access something it shouldn’t)&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;All sessions by Mark Russinovich&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;It goes without saying, Mark Russinovich is the king of interesting presentations.&amp;nbsp; Whenever I go to a “case of the unexpected” session I come out with some tool that I can use immediately to resolve perf. issues or other annoyances on my personal machines.&amp;nbsp; I am sure that a lot of you have already seen these but if you havent, here is a link to the sessions for 2007-2009 in webcast form &lt;A title=http://technet.microsoft.com/en-us/sysinternals/bb963887.aspx href="http://technet.microsoft.com/en-us/sysinternals/bb963887.aspx" mce_href="http://technet.microsoft.com/en-us/sysinternals/bb963887.aspx"&gt;http://technet.microsoft.com/en-us/sysinternals/bb963887.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;While you are there, check out the autoruns app to clean up your machine from apps that are launched at start up to speed up startup on your machines.&amp;nbsp; And, of course, as Mark says “When in doubt, use process explorer”:)&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Resources for my sessions&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;For the 2nd year in a row I presented a session about debugging ASP.NET issues with WinDBG and sprinkled in some demos of new mixed-mode dump debugging in Visual Studio .NET 2010.&lt;/P&gt;
&lt;P&gt;If you went to see it, first off thank you:) and second, here are links to some of the tools I used.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx" mce_href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx"&gt;Debugging Tools for Windows (Includes Windbg)&lt;/A&gt; &lt;BR&gt;&lt;A href="http://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&amp;amp;displaylang=en" mce_href="http://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&amp;amp;displaylang=en"&gt;Debug Diag 1.1 – Great tool for creating memory dumps and analyzing them&lt;/A&gt; &lt;BR&gt;&lt;A href="http://www.wintellect.com/CS/blogs/jrobbins/archive/2008/09/17/windbg-cmdtree-file-that-eases-some-sos-pain.aspx" mce_href="http://www.wintellect.com/CS/blogs/jrobbins/archive/2008/09/17/windbg-cmdtree-file-that-eases-some-sos-pain.aspx"&gt;Post on using .CmdTree to get a Treview list with commands&lt;/A&gt; &lt;BR&gt;&lt;A href="http://blogs.msdn.com/tess/archive/2009/05/12/debug-diag-script-for-troubleshooting-net-2-0-memory-leaks.aspx" mce_href="http://blogs.msdn.com/tess/archive/2009/05/12/debug-diag-script-for-troubleshooting-net-2-0-memory-leaks.aspx"&gt;My Debug Diag script for analyzing .net memory leaks&lt;/A&gt; &lt;BR&gt;&lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=56fc92ee-a71a-4c73-b628-ade629c89499&amp;amp;DisplayLang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyID=56fc92ee-a71a-4c73-b628-ade629c89499&amp;amp;DisplayLang=en"&gt;IIS Resource Kit (contains tinyget to do quick and dirty stress tests)&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Podcasts, webcasts and interviews&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;As I mentioned in my last post, I had a chance to record some webcasts with Carl Franklin of &lt;A href="http://www.dnrtv.com/" mce_href="http://www.dnrtv.com/"&gt;DNRTV&lt;/A&gt; and a podcast with Scott Hanselman for &lt;A href="http://www.hanselminutes.com/" mce_href="http://www.hanselminutes.com"&gt;Hanselminutes&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;DotNetRocks TV – &lt;A href="http://www.dnrtv.com/default.aspx?showNum=157" mce_href="http://www.dnrtv.com/default.aspx?showNum=157"&gt;30 minute webcast with demos on .net debugging&lt;/A&gt; &lt;BR&gt;Channel 9 with Hanselman – &lt;A href="http://www.hanselman.com/blog/HanselminutesOn9DebuggingCrashDumpsWithTessFerrandezAndVS2010.aspx" mce_href="http://www.hanselman.com/blog/HanselminutesOn9DebuggingCrashDumpsWithTessFerrandezAndVS2010.aspx"&gt;10-15 min webcast with a demo on how to debug dumps with Visual Studio .NET 2010&lt;/A&gt; &lt;BR&gt;Hanselminutes – &lt;A href="http://www.hanselminutes.com/default.aspx?showID=204" mce_href="http://www.hanselminutes.com/default.aspx?showID=204"&gt;30 minute podcast about .net debugging&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;I also had a chance to record some TechED TechTalk Interviews last week (where I was the interviewer:)). &lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.msteched.com/online/view.aspx?tid=bb19ad6d-355d-43aa-a1ec-8df96d07ecf7" mce_href="http://www.msteched.com/online/view.aspx?tid=bb19ad6d-355d-43aa-a1ec-8df96d07ecf7"&gt;TechTalk about MEF (Managed Extensibility Framework)&lt;/A&gt; with &lt;A href="http://blog.noop.se/" mce_href="http://blog.noop.se/"&gt;Magnus Mårtensson&lt;/A&gt; from dotway&amp;nbsp; &lt;BR&gt;&lt;A href="http://www.msteched.com/online/view.aspx?tid=40858c4c-9624-4912-8b6c-f6b85db9bf7b" mce_href="http://www.msteched.com/online/view.aspx?tid=40858c4c-9624-4912-8b6c-f6b85db9bf7b"&gt;TechTalk about Parallel Computing&lt;/A&gt; with Tiberiu Covaci&lt;/P&gt;
&lt;P&gt;Tiberiu was on the road with us at Oredev and TechED and I think he is at the PDC now as well, doing &lt;A href="http://www.cloudcasts.net/Default.aspx?presenter=Tiberiu%20Covaci" mce_href="http://www.cloudcasts.net/Default.aspx?presenter=Tiberiu%20Covaci"&gt;5 minute interviews&lt;/A&gt; with lots of people, like Jon Flanders, Scott Hanselman (again),&amp;nbsp; Julie Lerman, Scott Allen etc. etc.&amp;nbsp; and last but not least a really cool &lt;A href="http://www.cloudcasts.net/ViewWebcast.aspx?webcastid=2521447950052560369" mce_href="http://www.cloudcasts.net/ViewWebcast.aspx?webcastid=2521447950052560369"&gt;5 min interview&lt;/A&gt; with &lt;A href="http://www.zefrank.com/theshow/" mce_href="http://www.zefrank.com/theshow/"&gt;Ze Frank&lt;/A&gt; that ended up lasting 11 minutes:) &lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Have a good one,&lt;/P&gt;
&lt;P&gt;Tess &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9924326" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry><entry><title>Recap of Oredev and some .net debugging videos</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/11/06/recap-of-oredev-and-some-net-debugging-videos.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/11/06/recap-of-oredev-and-some-net-debugging-videos.aspx</id><published>2009-11-06T14:21:00Z</published><updated>2009-11-06T14:21:00Z</updated><content type="html">&lt;P&gt;This week I attended and spoke at the &lt;A href="http://www.oredev.org/" mce_href="http://www.oredev.org"&gt;Oredev&lt;/A&gt; conference in Malmö Sweden, and it was great fun as usual. It was a pretty productive few days with a lot of good talks and conversations with some really cool people. &lt;/P&gt;
&lt;P&gt;I’ll put up a link to the talk as it becomes available &lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.hanselman.com/blog/HanselminutesOn9DebuggingCrashDumpsWithTessFerrandezAndVS2010.aspx" mce_href="http://www.hanselman.com/blog/HanselminutesOn9DebuggingCrashDumpsWithTessFerrandezAndVS2010.aspx"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Channel9 video and chat with Scott Hanselman for Hanselminutes&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.hanselman.com/blog/HanselminutesOn9DebuggingCrashDumpsWithTessFerrandezAndVS2010.aspx" mce_href="http://www.hanselman.com/blog/HanselminutesOn9DebuggingCrashDumpsWithTessFerrandezAndVS2010.aspx"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px 10px 5px 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image align=left src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/RecapofOredevandsome.netdebuggingvideos_D7B6/image_7.png" width=244 height=156 mce_src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/RecapofOredevandsome.netdebuggingvideos_D7B6/image_7.png"&gt;&lt;/A&gt;I got to meet “The man, the myth, the legend” Scott Hanselman and he recorded a 10 minute demo for Channel9 where I showed him how to debug a .Net performance issue using Memory dumps in Visual Studio .NET 2010 Beta 2.&lt;/P&gt;
&lt;P&gt;&lt;A title=http://www.hanselman.com/blog/HanselminutesOn9DebuggingCrashDumpsWithTessFerrandezAndVS2010.aspx href="http://www.hanselman.com/blog/HanselminutesOn9DebuggingCrashDumpsWithTessFerrandezAndVS2010.aspx" mce_href="http://www.hanselman.com/blog/HanselminutesOn9DebuggingCrashDumpsWithTessFerrandezAndVS2010.aspx"&gt;http://www.hanselman.com/blog/HanselminutesOn9DebuggingCrashDumpsWithTessFerrandezAndVS2010.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;We also had a really nice chat about debugging (kind of a 101 primer) for hanselminutes that should be out on &lt;A href="http://www.hanselminutes.com/" mce_href="http://www.hanselminutes.com"&gt;http://www.hanselminutes.com&lt;/A&gt; sometime in the near future.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;.NET Rocks and dnr TV with Carl Franklin and Richard Campbell&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Earlier this year I had a chance to speak to my pod-casting idols Carl and Richard on &lt;A href="http://www.dotnetrocks.com/" mce_href="http://www.dotnetrocks.com/"&gt;.NET Rocks&lt;/A&gt; about &lt;A href="http://www.dotnetrocks.com/default.aspx?showNum=427" mce_href="http://www.dotnetrocks.com/default.aspx?showNum=427"&gt;debugging .net apps&lt;/A&gt;.&amp;nbsp; They were also hanging out in the hallways of Oredev and it was a treat to meet them in person.&amp;nbsp; &lt;A href="http://www.dnrtv.com/" mce_href="http://www.dnrtv.com/"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; MARGIN-LEFT: 0px; BORDER-TOP: 0px; MARGIN-RIGHT: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image align=right src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/RecapofOredevandsome.netdebuggingvideos_D7B6/image_9.png" width=227 height=70 mce_src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/RecapofOredevandsome.netdebuggingvideos_D7B6/image_9.png"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;To follow up on that talk I showed Carl some debugging demos with Windbg and sos.dll, as well as a Visual Studio 2010 demo for an episode of &lt;A href="http://www.dnrtv.com/" mce_href="http://www.dnrtv.com/"&gt;dnrTV&lt;/A&gt;.&amp;nbsp; I’ll post a link to it when it comes out but if you haven’t done so before, you should definitely check out .net rocks podcasts and dnrTV episodes.&amp;nbsp; Very entertaining and educational.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.youtube.com/watch?v=xBufFERihK0" mce_href="http://www.youtube.com/watch?v=xBufFERihK0"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px 5px 0px 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=carlpub2 border=0 alt=carlpub2 align=left src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/RecapofOredevandsome.netdebuggingvideos_D7B6/carlpub2_3.png" width=244 height=182 mce_src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/RecapofOredevandsome.netdebuggingvideos_D7B6/carlpub2_3.png"&gt;&lt;/A&gt; &lt;BR&gt;Carl is not only a good podcaster/interviewer, it turns out that he is also really good at playing the guitar and singing.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;On Wednesday night he and &lt;A href="http://wildermuth.com/" mce_href="http://wildermuth.com/"&gt;Shawn Wildermuth&lt;/A&gt; pulled out their guitars and had an impromptu jam session at the Bishops Arms pub in Malmö.&lt;/P&gt;
&lt;P&gt;Scott recorded it for the world to view &lt;A href="http://www.youtube.com/watch?v=xBufFERihK0" mce_href="http://www.youtube.com/watch?v=xBufFERihK0"&gt;on youtube&lt;/A&gt; but the recording really didn’t do it the justice it deserved. &lt;/P&gt;
&lt;P&gt;Pure awesome!!!&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;A href="http://www.youtube.com/watch?v=lz_0DIFCS9o" mce_href="http://www.youtube.com/watch?v=lz_0DIFCS9o"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image align=right src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/RecapofOredevandsome.netdebuggingvideos_D7B6/image_8.png" width=244 height=166 mce_src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/RecapofOredevandsome.netdebuggingvideos_D7B6/image_8.png"&gt;&lt;/A&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Surface demo in the Microsoft booth&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The Swedish Microsoft booth featured a Surface table where you could try it out.&amp;nbsp; We have one at work so I’ve seen it before but still, they were showing some really amazing stuff on it. &lt;/P&gt;
&lt;P&gt;You can see a demo &lt;A href="http://www.youtube.com/watch?v=lz_0DIFCS9o" mce_href="http://www.youtube.com/watch?v=lz_0DIFCS9o"&gt;here&lt;/A&gt;, where Johan Lindfors who is now blogging on &lt;A title=http://programmeramera.se/ href="http://programmeramera.se/" mce_href="http://programmeramera.se/"&gt;http://programmeramera.se/&lt;/A&gt; shows it off.&lt;/P&gt;
&lt;P&gt;&lt;A title=http://buzzfrog.blogs.com/zabrak/ href="http://buzzfrog.blogs.com/zabrak/" mce_href="http://buzzfrog.blogs.com/zabrak/"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;All in all, a very good few days… can’t wait til next time…&lt;/P&gt;
&lt;P&gt;Now it’s off to &lt;A href="http://www.microsoft.com/europe/teched/" mce_href="http://www.microsoft.com/europe/teched/"&gt;TechEd Berlin&lt;/A&gt; for a week of fun (Shawn promised to bring his guitar again) before conference season is over for me for this year.&lt;/P&gt;
&lt;P&gt;/Tess&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9918591" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /></entry><entry><title>WOHOO!!!, Debug Diag 64bit is finally released</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/10/29/wohoo-debug-diag-64bit-is-finally-released.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/10/29/wohoo-debug-diag-64bit-is-finally-released.aspx</id><published>2009-10-29T10:49:01Z</published><updated>2009-10-29T10:49:01Z</updated><content type="html">&lt;p&gt;For all of you who have been asking me if there is a 64bit version of Debug Diag (used to debug 64 bit processes), I am happy to say that yes, Debug Diag 1.1 64bit is now released.&lt;/p&gt;  &lt;p&gt;You can download it here:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a title="http://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&amp;amp;displaylang=en#filelist" href="http://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&amp;amp;displaylang=en#filelist"&gt;http://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&amp;amp;displaylang=en#filelist&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;And an updated whitepaper talking about how to use it is available here:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=4A2FBD0D-0635-440C-A08B-ED81BDBB5960&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=4A2FBD0D-0635-440C-A08B-ED81BDBB5960&amp;amp;displaylang=en&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Neither this version (nor the 32bit one) officially support debugging/analyzing on Vista/2008/Win7 because of some known compatibility issues (being looked at for future versions), however for a lot of tasks it works quite well on those operating systems as well.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9914618" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="General debugging tidbits" scheme="http://blogs.msdn.com/tess/archive/tags/General+debugging+tidbits/default.aspx" /><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry><entry><title>.NET Hang Case study: The danger of locking on strings</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/10/19/net-hang-case-study-the-danger-of-locking-on-strings.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/10/19/net-hang-case-study-the-danger-of-locking-on-strings.aspx</id><published>2009-10-19T13:51:00Z</published><updated>2009-10-19T13:51:00Z</updated><content type="html">&lt;P&gt;I had an interesting case today where an asp.net app was stuck in a true deadlock.&amp;nbsp; In other words two threads were both waiting for resources that the other thread owned.&lt;/P&gt;
&lt;P&gt;The scenario in these cases usually goes something like this:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;FunctionA (locks on ResourceA) and calls FunctionB where it needs ResourceB &lt;BR&gt;FunctionB (locks on ResourceB) and calls FunctionA where it needs ResourceA&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;And is typically pretty easy to spot, understand and fix…&lt;/P&gt;
&lt;P&gt;However, in this particular case things were a bit different.&lt;/P&gt;
&lt;P&gt;We had gotten memory dumps of the process and after loading them up in windbg, loding sos.dll, and running ~* e !clrstack to see what the threads were working on, we found that a lot of the threads were sitting in System.Threading.Monitor.Enter like below, indicating that they were waiting on a lock…&lt;/P&gt;
&lt;DIV class=SampleCode&gt;0:015&amp;gt; !clrstack &lt;BR&gt;OS Thread Id: 0x19c0 (15) &lt;BR&gt;ESP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EIP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;0240f1a0 7d61d06f [GCFrame: 0240f1a0] &lt;BR&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;0240f2dc 7d61d06f [HelperMethodFrame: 0240f2dc] System.Threading.Monitor.Enter(System.Object)&lt;/FONT&gt;&lt;/STRONG&gt; &lt;BR&gt;0240f330 10250ad1 ClassA.ThisFunctionLocksOnStringA() &lt;BR&gt;0240f35c 10250a8e _Default.Page_Load(System.Object, System.EventArgs) &lt;BR&gt;0240f364 66f2a7ff System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr, System.Object, System.Object, System.EventArgs) &lt;BR&gt;0240f374 660b2fb4 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(System.Object, System.EventArgs) &lt;BR&gt;0240f388 660ac4b4 System.Web.UI.Control.OnLoad(System.EventArgs) &lt;BR&gt;0240f39c 660ac4f3 System.Web.UI.Control.LoadRecursive() &lt;BR&gt;0240f3b4 660a85a4 System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean) &lt;BR&gt;0240f50c 660a81d4 System.Web.UI.Page.ProcessRequest(Boolean, Boolean) &lt;BR&gt;0240f544 660a8101 System.Web.UI.Page.ProcessRequest() &lt;BR&gt;0240f57c 660a8096 System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext) &lt;BR&gt;0240f588 660a8072 System.Web.UI.Page.ProcessRequest(System.Web.HttpContext) &lt;BR&gt;0240f59c 102508a5 ASP.default_aspx.ProcessRequest(System.Web.HttpContext) &lt;BR&gt;0240f5a0 660ae546 System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() &lt;BR&gt;0240f5d4 66081a7c System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef) &lt;BR&gt;0240f614 6608cd13 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception) &lt;BR&gt;0240f664 66080ffc System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object) &lt;BR&gt;0240f680 6608456c System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest) &lt;BR&gt;0240f6b4 66084213 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest) &lt;BR&gt;0240f6c4 660833ac System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32) &lt;BR&gt;0240f8d8 79f68c4e [ContextTransitionFrame: 0240f8d8] &lt;BR&gt;0240f90c 79f68c4e [GCFrame: 0240f90c] &lt;BR&gt;0240fa68 79f68c4e [ComMethodFrame: 0240fa68] &lt;/DIV&gt;
&lt;P&gt;Note:&amp;nbsp; I have given the methods in ClassA (and later on ClassB and ClassC) names that tell us what they are locking on so that it will be easier to follow along.&amp;nbsp; If this were a real scenairo you would obviously have to look at the code for ClassA.ThisFunctionLocksOnStringA() to see what it was locking on:)&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Finding the deadlock&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;I loaded up SOSEX.dll from &lt;A title=http://www.stevestechspot.com/SOSEXUpdatedV11Available.aspx#ac51f1a46-0016-4f24-9ca7-61125105c6e1 href="http://www.stevestechspot.com/SOSEXUpdatedV11Available.aspx#ac51f1a46-0016-4f24-9ca7-61125105c6e1" mce_href="http://www.stevestechspot.com/SOSEXUpdatedV11Available.aspx#ac51f1a46-0016-4f24-9ca7-61125105c6e1"&gt;http://www.stevestechspot.com/SOSEXUpdatedV11Available.aspx#ac51f1a46-0016-4f24-9ca7-61125105c6e1&lt;/A&gt; and ran !dlk which looks for deadlocks.&lt;/P&gt;
&lt;DIV class=SampleCode&gt;0:026&amp;gt; !dlk &lt;BR&gt;Deadlock detected: &lt;BR&gt;CLR thread 26 holds sync block 001e10e4 OBJ:&lt;STRONG&gt;06e401d0&lt;/STRONG&gt;[System.String] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waits sync block 001e12c4 OBJ:&lt;STRONG&gt;06ec6618&lt;/STRONG&gt;[System.String] STRVAL=LOCKA &lt;BR&gt;CLR thread 55 holds sync block 001e12c4 OBJ:&lt;STRONG&gt;06ec6618&lt;/STRONG&gt;[System.String] STRVAL=LOCKA &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waits sync block 001e10e4 OBJ:&lt;STRONG&gt;06e401d0&lt;/STRONG&gt;[System.String] &lt;BR&gt;CLR Thread 26 is waiting at ClassA.ThisFunctionAlsoLocksOnStringA()+0x6(IL) &lt;BR&gt;CLR Thread 55 is waiting at ClassB.ThisFunctionLocksOnStringB()+0x6(IL) 
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;1 deadlock detected.&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;This tells us that we have a deadlock between CLR Thread 26 and CLR Thread 55, where they both own locks on resources that the other thread is waiting for, so now we know that we have a deadlock and which threads are involved.&lt;/P&gt;
&lt;P&gt;!dlk is really great for looking at deadlocks but it has one little snag and that is that it reports the CLR thread numbers which is different than the logical thread IDs that we are used to.&amp;nbsp;&amp;nbsp; However, we can “easily” map them to the logical thread IDs if we use the !threads output.&amp;nbsp; The 2nd column in !threads shows the CLR thread ID in hex.&lt;/P&gt;
&lt;P&gt;CLR Thread 26 (0x1a) = logical thread 44 &lt;BR&gt;CLR Thread 55 (0x37) = logical thread 73&lt;/P&gt;
&lt;DIV class=SampleCode&gt;0:026&amp;gt; !threads &lt;BR&gt;ThreadCount: 65 &lt;BR&gt;UnstartedThread: 0 &lt;BR&gt;BackgroundThread: 65 &lt;BR&gt;PendingThread: 0 &lt;BR&gt;DeadThread: 0 &lt;BR&gt;Hosted Runtime: no &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PreEmptive&amp;nbsp;&amp;nbsp; GC Alloc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Lock &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ID OSID ThreadOBJ&amp;nbsp;&amp;nbsp;&amp;nbsp; State&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GC&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Context&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Domain&amp;nbsp;&amp;nbsp; Count APT Exception &lt;BR&gt;... &lt;BR&gt;&amp;nbsp; 44&amp;nbsp;&amp;nbsp; 1a 1b58 0ee85eb0&amp;nbsp;&amp;nbsp; 380b220 Enabled&amp;nbsp; 00000000:00000000 001e6608&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2 MTA (Threadpool Worker) &lt;BR&gt;... &lt;BR&gt;&amp;nbsp; 73&amp;nbsp;&amp;nbsp; 37 1610 0eea4bc0&amp;nbsp;&amp;nbsp; 380b220 Enabled&amp;nbsp; 00000000:00000000 001e6608&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2 MTA (Threadpool Worker) &lt;BR&gt;...&lt;/DIV&gt;
&lt;P&gt;We could also have avoided doing the math here by dumping out the active locks with !sos.syncblk&lt;/P&gt;
&lt;DIV class=SampleCode&gt;0:026&amp;gt; !sos.syncblk &lt;BR&gt;Index SyncBlock MonitorHeld Recursion Owning Thread Info&amp;nbsp; SyncBlock Owner &lt;BR&gt;&amp;nbsp;&amp;nbsp; 22 001e10e4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 41&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 0ee85eb0&amp;nbsp; 1b58&amp;nbsp; 44&amp;nbsp;&amp;nbsp; 06e401d0 System.String &lt;BR&gt;&amp;nbsp;&amp;nbsp; 32 001e12c4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 41&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 0eea4bc0&amp;nbsp; 1610&amp;nbsp; 73&amp;nbsp;&amp;nbsp; 06ec6618 System.String &lt;BR&gt;----------------------------- &lt;BR&gt;Total&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 35 &lt;BR&gt;CCW&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2 &lt;BR&gt;RCW&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 &lt;BR&gt;ComClassFactory 0 &lt;BR&gt;Free&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&lt;/DIV&gt;
&lt;P&gt;Syncblk here tells us that thread 44 owns the lock to syncblock 06e401d0 (so t44 is CLR Thread 26) and thread 73 owns the lock to syncblock 06ec6618 (so t73 is CLR Thread 55 in the !dlk output).&lt;/P&gt;
&lt;P&gt;Ok, getting back off that tangent again:), now we know that 44 is waiting on 73 and 73 is waiting on 44, but why?&lt;/P&gt;
&lt;P&gt;The stacks for thread 44 and thread 73 look like this&lt;/P&gt;
&lt;DIV class=SampleCode&gt;0:044&amp;gt; !clrstack &lt;BR&gt;OS Thread Id: 0x1b58 (44) &lt;BR&gt;ESP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EIP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;116ee5f0 7d61d06f [GCFrame: 116ee5f0] &lt;BR&gt;116ee72c 7d61d06f [HelperMethodFrame: 116ee72c] System.Threading.Monitor.Enter(System.Object) &lt;BR&gt;116ee780 10250757 ClassA.ThisFunctionAlsoLocksOnStringA() &lt;BR&gt;116ee7b0 102506bf ClassC.ThisFunctionLocksOnStringC() &lt;BR&gt;116ee7dc 1025064e Default2.Page_Load(System.Object, System.EventArgs) &lt;BR&gt;… &lt;BR&gt;&lt;BR&gt;0:073&amp;gt; !clrstack &lt;BR&gt;OS Thread Id: 0x1610 (73) &lt;BR&gt;ESP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EIP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;1287e770 7d61d06f [GCFrame: 1287e770] &lt;BR&gt;1287e8ac 7d61d06f [HelperMethodFrame: 1287e8ac] System.Threading.Monitor.Enter(System.Object) &lt;BR&gt;1287e900 10250b6f ClassB.ThisFunctionLocksOnStringB() &lt;BR&gt;1287e930 10250ad7 ClassA.ThisFunctionLocksOnStringA() &lt;BR&gt;1287e95c 10250a8e _Default.Page_Load(System.Object, System.EventArgs) &lt;BR&gt;…&lt;/DIV&gt;
&lt;P&gt;44 is waiting for the lock on StringA (where StringA="LockA") which 73 took in ClassA.ThisFunctionLocksOnStringA() before calling into ClassB.ThisFunctionLocksOnStringB(), so that is all well and good.&lt;/P&gt;
&lt;P&gt;The question here is why does Thread 44 hold a lock on StringB?, there is no method on the stack that locked on StringB…&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Why are we locking?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;ClassB and ClassC look like this (with their own individual lock objects LockB and LockC):&lt;/P&gt;
&lt;DIV class=SampleCode&gt;public class ClassB &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static string LockB = ""; 
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void ThisFunctionLocksOnStringB() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lock (LockB) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Do some stuff &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;... &lt;BR&gt;} &lt;BR&gt;&lt;BR&gt;public class ClassC &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static string LockC = ""; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void ThisFunctionLocksOnStringC() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lock (LockC) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ClassA.ThisFunctionAlsoLocksOnStringA(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/P&gt;
&lt;P&gt;... &lt;BR&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;At first sight, LockB and LockC look like different objects, but in reality they are just pointers to the same string constant “”, so in reality this would be the same as saying lock(“”) in both cases.&amp;nbsp; In fact if you did have a 3rd function saying lock(“”)&amp;nbsp; this would also have to wait until the lock for LockB or LockC was released.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Summary&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;When using locks, best practice is to use a private static object so that you can control who/where code locks on this object.&lt;/P&gt;
&lt;P&gt;There are some good guidelines for locks in general at: &lt;BR&gt;&lt;A title=http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx href="http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx" mce_href="http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx"&gt;http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx&lt;/A&gt; &lt;BR&gt;and &lt;BR&gt;&lt;A title=http://www.guidanceshare.com/wiki/.NET_2.0_Performance_Guidelines_-_Locking_and_Synchronization href="http://www.guidanceshare.com/wiki/.NET_2.0_Performance_Guidelines_-_Locking_and_Synchronization" mce_href="http://www.guidanceshare.com/wiki/.NET_2.0_Performance_Guidelines_-_Locking_and_Synchronization"&gt;http://www.guidanceshare.com/wiki/.NET_2.0_Performance_Guidelines_-_Locking_and_Synchronization&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;Laters, &lt;BR&gt;Tess&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9909070" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="Performance issues and hangs" scheme="http://blogs.msdn.com/tess/archive/tags/Performance+issues+and+hangs/default.aspx" /><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry><entry><title>Debug Diag: mscorwks.dll is responsible for 372.46 MBytes worth of outstanding allocations</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/10/09/debug-diag-mscorwks-dll-is-responsible-for-372-46-mbytes-worth-of-outstanding-allocations.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/10/09/debug-diag-mscorwks-dll-is-responsible-for-372-46-mbytes-worth-of-outstanding-allocations.aspx</id><published>2009-10-09T15:56:27Z</published><updated>2009-10-09T15:56:27Z</updated><content type="html">&lt;p&gt;I got an email today on an issue that I think is pretty common when you try to memory leak analysis on a dump with &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&amp;amp;displaylang=en"&gt;debug diag&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;They had set up a leak rule in debug diag to monitor for leaks and then ran the memory analysis on it to see what was leaking and the results looked something like this:&lt;/p&gt;  &lt;table border="1" width="887"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&amp;#160; Warning &lt;/td&gt;        &lt;td width="564"&gt;&lt;b&gt;mscorwks.dll&lt;/b&gt; is responsible for &lt;b&gt;372.46 MBytes&lt;/b&gt; worth of outstanding allocations. The following are the top 2 memory consuming functions:           &lt;br /&gt;&lt;b&gt;mscorwks!EEVirtualAlloc+119&lt;/b&gt;: &lt;b&gt;312.00 MBytes&lt;/b&gt; worth of outstanding allocations.           &lt;br /&gt;&lt;b&gt;mscorwks!EEHeapAlloc+142&lt;/b&gt;: &lt;b&gt;60.46 MBytes&lt;/b&gt; worth of outstanding allocations. &lt;/td&gt;        &lt;td width="263"&gt;If this is unexpected, please contact the vendor of this module, &lt;b&gt;Microsoft Corporation&lt;/b&gt;, for further assistance with this issue. &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;So what does this mean?&amp;#160; Is mscorwks a really leaky component? &lt;/p&gt;  &lt;p&gt;Turns out that debug diag leak monitoring feature is really good when it comes to native leaks (non .net), and not so good with high .net memory usage.&lt;/p&gt;  &lt;p&gt;The reason for this is pretty simple.&amp;#160; If you have a native component (like a COM+ component) making allocations etc. debug diag will pick up the stacks that did virtualalloc or heapalloc and point out the ones that haven’t de-allocated their memory so you can see stacks that still have outstanding allocations.&lt;/p&gt;  &lt;p&gt;As most of you know, memory management in .NET is centralized through the garbage collector, so this means that any and all memory used for .net objects is actually allocated by the GC (through functions in&amp;#160; mscorwks.dll).&amp;#160;&amp;#160; This means that when you use something like debug diag, that focuses on native allocations, it will seem like mscorwks.dll is leaking, while what is really happening is that you have growing .net memory usage.&lt;/p&gt;  &lt;p&gt;The reason it says for you to contact Microsoft is because mscorwks.dll is part of the Microsoft .NET Framework, and while you are welcome to call our support to troubleshoot these kind of things, it will likely come down to high memory usage caused by the application in question.&lt;/p&gt;  &lt;p&gt;To troubleshoot these types of memory issues, a good start might be to go through the &lt;a href="http://blogs.msdn.com/tess/archive/2008/02/15/net-debugging-demos-lab-3-memory.aspx"&gt;memory leak labs&lt;/a&gt; or to look at any &lt;a href="http://blogs.msdn.com/tess/archive/tags/Memory+issues/default.aspx"&gt;posts tagged with memory&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Laters,&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9905425" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="Memory issues" scheme="http://blogs.msdn.com/tess/archive/tags/Memory+issues/default.aspx" /><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry><entry><title>Finding memory leaks with ANTS Memory Profiler</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/10/07/finding-memory-leaks-with-ants-memory-profiler.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/10/07/finding-memory-leaks-with-ants-memory-profiler.aspx</id><published>2009-10-07T14:05:40Z</published><updated>2009-10-07T14:05:40Z</updated><content type="html">&lt;p&gt;I was out looking for some sample scripts for tinyget and ran across this &lt;a href="http://devlicio.us/blogs/scott_seely/archive/2009/08/23/review-of-ants-memory-profiler.aspx"&gt;ANTS Memory Profiler review&lt;/a&gt; where Scott Seely has tested it out on some of &lt;a href="http://blogs.msdn.com/tess/pages/net-debugging-demos-information-and-setup-instructions.aspx"&gt;my debugging labs&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I haven’t had the time and/or opportunity to test it out myself but since many people have asked me if I had used it or what I thought of it I thought I’d just point you to someone who has instead:)&lt;/p&gt;  &lt;p&gt;Have fun,&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9904284" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="Memory issues" scheme="http://blogs.msdn.com/tess/archive/tags/Memory+issues/default.aspx" /><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry><entry><title>ASP.NET Case Study: Hang when loading assemblies</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/09/22/asp-net-case-study-hang-when-loading-assemblies.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/09/22/asp-net-case-study-hang-when-loading-assemblies.aspx</id><published>2009-09-22T16:03:00Z</published><updated>2009-09-22T16:03:00Z</updated><content type="html">&lt;P&gt;The other day I came across an issue where an ASP.NET site stopped responding and didn’t start serving requests again until the W3WP.exe process was restarted.&lt;/P&gt;
&lt;P&gt;We grabbed some memory dumps with debug diag before restarting the process to see what was going on. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Debugging the dumps:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;I opened the dump in windbg, and loaded up sos (.loadby sos mscorwks).&lt;/P&gt;
&lt;P&gt;As with all hang dumps I usually check what the threads are doing (~* kb) and I found that one thread (10) was initiating a garbage collection.&lt;/P&gt;
&lt;DIV class=SampleCode&gt;0:010&amp;gt; kb &lt;BR&gt;ChildEBP RetAddr&amp;nbsp; Args to Child&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;01cceeb4 7c827d0b 77e61d1e 00000280 00000000 ntdll!KiFastSystemCallRet &lt;BR&gt;01cceeb8 77e61d1e 00000280 00000000 01cceefc ntdll!NtWaitForSingleObject+0xc &lt;BR&gt;01ccef28 79e718fd 00000280 000000fa 00000000 kernel32!WaitForSingleObjectEx+0xac &lt;BR&gt;01ccef6c 79e718c6 00000280 000000fa 00000000 mscorwks!PEImage::LoadImage+0x199 &lt;BR&gt;01ccefbc 79e7187c 000000fa 00000000 00000000 mscorwks!CLREvent::WaitEx+0x117 &lt;BR&gt;01ccefcc 7a0e288e 000000fa 00000000 00000000 mscorwks!CLREvent::Wait+0x17 &lt;BR&gt;&lt;STRONG&gt;01ccf020 79f25226 00000000 9985f121 00032ca8 mscorwks!Thread::SysSuspendForGC+0x52a &lt;BR&gt;01ccf10c 79f25011 00000001 00000024 00000000 mscorwks!WKS::GCHeap::SuspendEE+0x16c &lt;BR&gt;01ccf130 79f24ef2 00000000 00000000 00000024 mscorwks!WKS::GCHeap::GarbageCollectGeneration+0x25b &lt;BR&gt;&lt;/STRONG&gt;01ccf1b8 79e74f4f 7a3867e8 00000024 00000000 mscorwks!WKS::gc_heap::try_allocate_more_space+0x1a0 &lt;BR&gt;01ccf1d4 79e74d29 7a3867e8 00000024 00000000 mscorwks!WKS::gc_heap::allocate_more_space+0x18 &lt;BR&gt;01ccf1f4 79e74cc2 00000022 00000000 00000009 mscorwks!WKS::GCHeap::Alloc+0x6c &lt;BR&gt;01ccf208 79ea3646 00000022 00000000 00000000 mscorwks!Alloc+0x72 &lt;BR&gt;01ccf244 79f13708 00000009 9985f2c5 00000000 mscorwks!SlowAllocateString+0x29 &lt;BR&gt;*** WARNING: Unable to verify checksum for mscorlib.ni.dll &lt;BR&gt;01ccf2e8 79342fb3 00000048 00000000 00000000 mscorwks!FramedAllocateString+0xa0 &lt;BR&gt;01ccf308 79342f5a 00000000 00000008 00000006 mscorlib_ni+0x282fb3 &lt;BR&gt;00000000 00000000 00000000 00000000 00000000 mscorlib_ni+0x282f5a&lt;/DIV&gt;
&lt;P&gt;This is really not all that uncommon since GCs happen quite frequently. What was interesting about this one though was that it was sitting in mscorwks!Thread::SysSuspendForGC which basically means that it is trying to suspend all the .net threads in order to get started with the garbage collection.&lt;/P&gt;
&lt;P&gt;Whenever you see a thread stuck in this, you are almost always running into some GC deadlock condition.&lt;/P&gt;
&lt;P&gt;To find out why we can threads can’t be suspended we can look at the !threads output to find out if any threads (other than the GC initiator) has preemptive GC disabled.&amp;nbsp; (This means that it can’t be suspended)&lt;/P&gt;
&lt;DIV class=SampleCode&gt;0:000&amp;gt; !threads &lt;BR&gt;ThreadCount: 12 &lt;BR&gt;UnstartedThread: 0 &lt;BR&gt;BackgroundThread: 11 &lt;BR&gt;PendingThread: 0 &lt;BR&gt;DeadThread: 1 &lt;BR&gt;Hosted Runtime: yes &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PreEmptive&amp;nbsp;&amp;nbsp; GC Alloc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Lock &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ID OSID ThreadOBJ&amp;nbsp;&amp;nbsp;&amp;nbsp; State&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GC&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Context&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Domain&amp;nbsp;&amp;nbsp; Count APT Exception &lt;BR&gt;&amp;nbsp; 10&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 5e5c 0010e5a0&amp;nbsp;&amp;nbsp; 1808220 Disabled 00000000:00000000 00136610&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3 MTA (GC) (Threadpool Worker) &lt;BR&gt;&amp;nbsp; 12&amp;nbsp;&amp;nbsp;&amp;nbsp; 2 52c0 00117b20&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; b220 Enabled&amp;nbsp; 00000000:00000000 000dc7d0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 MTA (Finalizer) &lt;BR&gt;&amp;nbsp; 13&amp;nbsp;&amp;nbsp;&amp;nbsp; 3 4ca0 0011c638&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1220 Enabled&amp;nbsp; 00000000:00000000 000dc7d0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 Ukn &lt;BR&gt;&amp;nbsp;&amp;nbsp; 8&amp;nbsp;&amp;nbsp;&amp;nbsp; 4 4034 0012f6b8&amp;nbsp;&amp;nbsp; 880a220 Enabled&amp;nbsp; 00000000:00000000 000dc7d0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 MTA (Threadpool Completion Port) &lt;BR&gt;&amp;nbsp; 14&amp;nbsp;&amp;nbsp;&amp;nbsp; 5 5424 00133818&amp;nbsp;&amp;nbsp;&amp;nbsp; 80a220 Enabled&amp;nbsp; 00000000:00000000 000dc7d0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 MTA (Threadpool Completion Port) &lt;BR&gt;XXXX&amp;nbsp;&amp;nbsp;&amp;nbsp; 8&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 0226e710&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 9820 Enabled&amp;nbsp; 00000000:00000000 000dc7d0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 Ukn &lt;BR&gt;&amp;nbsp; 19&amp;nbsp;&amp;nbsp;&amp;nbsp; 7 42ac 0226e350&amp;nbsp;&amp;nbsp; 880b220 Enabled&amp;nbsp; 00000000:00000000 000dc7d0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 MTA (Threadpool Completion Port) &lt;BR&gt;&amp;nbsp; 20&amp;nbsp;&amp;nbsp;&amp;nbsp; 6 5dbc 09d756e8&amp;nbsp;&amp;nbsp; 180b220 Enabled&amp;nbsp; 00000000:00000000 00136610&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2 MTA (Threadpool Worker) &lt;BR&gt;&amp;nbsp;&amp;nbsp; 5&amp;nbsp;&amp;nbsp;&amp;nbsp; 9 4f74 0014f238&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 220 Enabled&amp;nbsp; 00000000:00000000 000dc7d0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 Ukn &lt;BR&gt;&amp;nbsp; 17&amp;nbsp;&amp;nbsp;&amp;nbsp; a 4378 09d90880&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 220 Enabled&amp;nbsp; 00000000:00000000 000dc7d0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 Ukn &lt;BR&gt;&amp;nbsp; 23&amp;nbsp;&amp;nbsp;&amp;nbsp; c 5a4c 09ead790&amp;nbsp;&amp;nbsp; 880b220 Enabled&amp;nbsp; 00000000:00000000 000dc7d0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 MTA (Threadpool Completion Port) &lt;BR&gt;&amp;nbsp; 26&amp;nbsp;&amp;nbsp;&amp;nbsp; b 5230 09ece8f0&amp;nbsp;&amp;nbsp; 180b222 Disabled 00000000:00000000 00136610&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 MTA (Threadpool Worker)&lt;/DIV&gt;
&lt;P&gt;From the !threads output we can see that in fact thread 26 has preemptive GC disabled.&amp;nbsp; I’ve talked about this in &lt;A href="http://blogs.msdn.com/tess/archive/2007/03/12/net-hang-case-study-the-gc-loader-lock-deadlock-a-story-of-mixed-mode-dlls.aspx" mce_href="http://blogs.msdn.com/tess/archive/2007/03/12/net-hang-case-study-the-gc-loader-lock-deadlock-a-story-of-mixed-mode-dlls.aspx"&gt;earlier posts&lt;/A&gt;, but in short, some technologies like fusion (used to load assemblies) will disable GC preemption to avoid getting interrupted during some critical operations.&lt;/P&gt;
&lt;P&gt;So what is this thread doing…&amp;nbsp; the MyTools.MyAssemblyLoader constructor is trying to load up an assembly using Assembly.LoadFile, so that is why preemptive GC is disabled.&amp;nbsp; This is usually a very quick operation but here it is stuck waiting on some event before it can finish.&lt;/P&gt;
&lt;DIV class=SampleCode&gt;0:026&amp;gt; kb &lt;BR&gt;ChildEBP RetAddr&amp;nbsp; Args to Child&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;0df0cd90 7c827d0b 77e61d1e 00000c5c 00000000 ntdll!KiFastSystemCallRet &lt;BR&gt;0df0cd94 77e61d1e 00000c5c 00000000 00000000 ntdll!NtWaitForSingleObject+0xc &lt;BR&gt;0df0ce04 79e718fd 00000c5c ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xac &lt;BR&gt;0df0ce48 79e718c6 00000c5c ffffffff 00000000 mscorwks!PEImage::LoadImage+0x199 &lt;BR&gt;0df0ce98 79e7187c ffffffff 00000000 00000000 mscorwks!CLREvent::WaitEx+0x117 &lt;BR&gt;0df0cea8 79f90f81 ffffffff 00000000 00000000 mscorwks!CLREvent::Wait+0x17 &lt;BR&gt;0df0ceb8 79f917ba 7a390970 0230cc18 ffffffff mscorwks!CExecutionEngine::WaitForEvent+0x37 &lt;BR&gt;0df0cecc 7a15cfce 0230cc18 ffffffff 00000000 mscorwks!ClrWaitEvent+0x17 &lt;BR&gt;0df0cedc 7a153339 0df0d2ac 00000000 00000000 mscorwks!CSimpleFusionBindSink::Wait+0xe &lt;BR&gt;0df0cef8 7a1545d2 09ed0180 0013a868 00000200 mscorwks!BindHelper+0x7d &lt;BR&gt;0df0d194 7a2d0c7c 0df0d2ac 0013a868 00000000 mscorwks!ExplicitBind+0x1a6 &lt;BR&gt;0df0d4b0 793f583f 00000000 17b75570 17b75498 mscorwks!AssemblyNative::LoadFile+0x1de &lt;BR&gt;0df0d4d0 7934f2ed 00000000 00000000 17b7546c mscorlib_ni+0x33583f &lt;BR&gt;0df0d4f4 085f6ec4 7a3177c0 17b3df74 00000000 mscorlib_ni+0x28f2ed &lt;BR&gt;WARNING: Frame IP not in any known module. Following frames may be wrong. &lt;BR&gt;0df0d530 085f6646 17b70088 17b6f1b4 17b70088 0x85f6ec4 &lt;BR&gt;0df0d7c8 085f48a2 790d57b4 17b6e648 17b40284 0x85f6646 &lt;BR&gt;*** WARNING: Unable to verify checksum for System.Data.ni.dll &lt;BR&gt;0df0dc10 651a82d5 17b5275c 79103ae8 00000000 0x85f48a2 &lt;BR&gt;0df0dff0 79f23aa2 95b9e085 026d1f54 17893ecc System_Data_ni!_load_config_used+0x56c45 &lt;BR&gt;0df0e0a0 00000000 00000000 00000000 00000000 mscorwks!COMNlsInfo::nativeChangeCaseString+0x18f 
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;0:026&amp;gt; !sos.clrstack &lt;BR&gt;OS Thread Id: 0x5230 (26) &lt;BR&gt;ESP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EIP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;0df0d200 7c8285ec [HelperMethodFrame_PROTECTOBJ: 0df0d200] System.Reflection.Assembly.nLoadFile(System.String, System.Security.Policy.Evidence) &lt;BR&gt;0df0d4b8 793f583f System.Reflection.Assembly.LoadFile(System.String) &lt;BR&gt;0df0d4cc 085f704d MyTools.MyAssemblyLoader..ctor(System.String) &lt;BR&gt;... &lt;BR&gt;0df0ebb0 083e85b0 MyAPP.Default.Page_Load(System.Object, System.EventArgs) &lt;BR&gt;0df0ed10 698a1928 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr, System.Object, System.Object, System.EventArgs) &lt;BR&gt;0df0ed20 6629769f System.Web.Util.CalliEventHandlerDelegateProxy.Callback(System.Object, System.EventArgs) &lt;BR&gt;0df0ed34 66143a84 System.Web.UI.Control.OnLoad(System.EventArgs) &lt;BR&gt;0df0ed44 66143ad0 System.Web.UI.Control.LoadRecursive() &lt;BR&gt;0df0ed58 66155106 System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean) &lt;BR&gt;0df0ef10 66154a1b System.Web.UI.Page.ProcessRequest(Boolean, Boolean) &lt;BR&gt;0df0ef48 66154967 System.Web.UI.Page.ProcessRequest() &lt;BR&gt;0df0ef80 66154887 System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext) &lt;BR&gt;0df0ef88 6615481a System.Web.UI.Page.ProcessRequest(System.Web.HttpContext) &lt;BR&gt;0df0ef9c 083e826e ASP.default_aspx.ProcessRequest(System.Web.HttpContext) &lt;BR&gt;0df0efa8 65ff27d4 System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() &lt;BR&gt;0df0efdc 65fc15b5 System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef) &lt;BR&gt;0df0f01c 65fd32e0 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception) &lt;BR&gt;0df0f06c 65fc0225 System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object) &lt;BR&gt;0df0f088 65fc550b System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest) &lt;BR&gt;0df0f0bc 65fc5212 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest) &lt;BR&gt;0df0f0c8 65fc3587 System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32) &lt;BR&gt;0df0f278 79f35ee8 [ContextTransitionFrame: 0df0f278] &lt;BR&gt;0df0f2c8 79f35ee8 [GCFrame: 0df0f2c8] &lt;BR&gt;0df0f420 79f35ee8 [ComMethodFrame: 0df0f420] &lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Looking around at other threads, we find another thread that is also loading up an assembly from the same location so this is probably the thread that will set the event so that thread 26 can continue.&lt;/P&gt;
&lt;DIV class=SampleCode&gt;0:020&amp;gt; kL 2000 &lt;BR&gt;ChildEBP RetAddr&amp;nbsp; &lt;BR&gt;0993cec0 7c827d0b ntdll!KiFastSystemCallRet &lt;BR&gt;0993cec4 77e61d1e ntdll!NtWaitForSingleObject+0xc &lt;BR&gt;0993cf34 79e718fd kernel32!WaitForSingleObjectEx+0xac &lt;BR&gt;0993cf78 79e718c6 mscorwks!PEImage::LoadImage+0x199 &lt;BR&gt;0993cfc8 79e7187c mscorwks!CLREvent::WaitEx+0x117 &lt;BR&gt;0993cfd8 79f40d79 mscorwks!CLREvent::Wait+0x17 &lt;BR&gt;0993cfe8 79f40e96 mscorwks!WKS::GCHeap::WaitUntilGCComplete+0x32 &lt;BR&gt;0993d024 79e7ee77 mscorwks!Thread::RareDisablePreemptiveGC+0x1a1 &lt;BR&gt;0993d05c 79e75c65 mscorwks!CrstBase::Enter+0x1e6 &lt;BR&gt;0993d060 79e75c59 mscorwks!EEEnterCriticalSection+0x9 &lt;BR&gt;0993d068 79e75c3b mscorwks!CExecutionEngine::AcquireLock+0x9 &lt;BR&gt;0993d074 79eb2f2d mscorwks!ClrEnterCriticalSection+0xf &lt;BR&gt;0993d080 7a1481d3 mscorwks!CCriticalSection::Lock+0x17 &lt;BR&gt;0993dd2c 7a14893a mscorwks!CAssemblyCacheItem::MoveAssemblyToFinalLocation+0x31f &lt;BR&gt;0993dd74 7a146e2d mscorwks!CAssemblyCacheItem::LegacyCommit+0x245 &lt;BR&gt;0993ddb0 7a16198e mscorwks!CAssemblyCacheItem::Commit+0x5d &lt;BR&gt;0993e45c 7a161e12 mscorwks!CAsmDownloadMgr::CreateAssembly+0x85b &lt;BR&gt;0993e498 7a162550 mscorwks!CAsmDownloadMgr::DoSetupPushToCache+0x50 &lt;BR&gt;0993e720 79f90e65 mscorwks!CAsmDownloadMgr::DoSetup+0x26a &lt;BR&gt;0993e76c 79f8f2cc mscorwks!CAssemblyDownload::DoSetup+0x7b &lt;BR&gt;0993e7a0 79f8f1e4 mscorwks!CAssemblyDownload::DownloadComplete+0xb6 &lt;BR&gt;0993e9fc 79f8f0ca mscorwks!CAssemblyDownload::KickOffDownload+0x19c &lt;BR&gt;0993ea64 79f2fd56 mscorwks!CAssemblyName::BindToObject+0x568 &lt;BR&gt;0993eaac 7a1545d2 mscorwks!BindHelper+0x6b &lt;BR&gt;0993ed48 7a2d0c7c mscorwks!ExplicitBind+0x1a6 &lt;BR&gt;0993f064 793f583f mscorwks!AssemblyNative::LoadFile+0x1de &lt;BR&gt;0993f0bc 79e7ae3e mscorlib_ni+0x33583f &lt;BR&gt;0993f0d0 00000000 mscorwks!MetaSig::MetaSig+0x125 
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;0:020&amp;gt; !sos.clrstack &lt;BR&gt;OS Thread Id: 0x5dbc (20) &lt;BR&gt;ESP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EIP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;0993edb4 7c8285ec [HelperMethodFrame_PROTECTOBJ: 0993edb4] System.Reflection.Assembly.nLoadFile(System.String, System.Security.Policy.Evidence) &lt;BR&gt;0993f06c 793f583f System.Reflection.Assembly.LoadFile(System.String) &lt;BR&gt;0993f080 085f704d MyTools.MyAssemblyLoader..ctor(System.String) &lt;BR&gt;0993f0b0 083e8612 MyAPP.Default.Page_Load(System.Object, System.EventArgs) &lt;BR&gt;0993f210 698a1928 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr, System.Object, System.Object, System.EventArgs) &lt;BR&gt;0993f220 6629769f System.Web.Util.CalliEventHandlerDelegateProxy.Callback(System.Object, System.EventArgs) &lt;BR&gt;0993f234 66143a84 System.Web.UI.Control.OnLoad(System.EventArgs) &lt;BR&gt;0993f244 66143ad0 System.Web.UI.Control.LoadRecursive() &lt;BR&gt;0993f258 66155106 System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean) &lt;BR&gt;0993f410 66154a1b System.Web.UI.Page.ProcessRequest(Boolean, Boolean) &lt;BR&gt;0993f448 66154967 System.Web.UI.Page.ProcessRequest() &lt;BR&gt;0993f480 66154887 System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext) &lt;BR&gt;0993f488 6615481a System.Web.UI.Page.ProcessRequest(System.Web.HttpContext) &lt;BR&gt;0993f49c 083e826e ASP.default_aspx.ProcessRequest(System.Web.HttpContext) &lt;BR&gt;0993f4a8 65ff27d4 System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() &lt;BR&gt;0993f4dc 65fc15b5 System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef) &lt;BR&gt;0993f51c 65fd32e0 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception) &lt;BR&gt;0993f56c 65fc0225 System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object) &lt;BR&gt;0993f588 65fc550b System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest) &lt;BR&gt;0993f5bc 65fc5212 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest) &lt;BR&gt;0993f5c8 65fc3587 System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32) &lt;BR&gt;0993f778 79f35ee8 [ContextTransitionFrame: 0993f778] &lt;BR&gt;0993f7c8 79f35ee8 [GCFrame: 0993f7c8] &lt;BR&gt;0993f920 79f35ee8 [ComMethodFrame: 0993f920] &lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;The problem here is that this thread has enabled preemptive GC again and the GC has suspended it so that it is now waiting for the GC to finish before it can finish.&lt;/P&gt;
&lt;P&gt;In other words we have a deadlock situation caused by a race condition with two threads loading the same dll at the same time:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Thread 10 – initiating GC – suspending all threads &lt;BR&gt;Thread 26 – can’t be suspended until it has finished loading the dll but is waiting for thread 20 to do so &lt;BR&gt;Thread 20 – waiting for the GC to finish to continue loading its dll&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Solutions:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This issue could be resolved by putting a lock around the Assembly.Load in the MyTools.MyAssemblyLoader constructor.&lt;/P&gt;
&lt;P&gt;However, this issue is actually fixed in &lt;A href="http://support.microsoft.com/?id=936757" mce_href="http://support.microsoft.com/?id=936757"&gt;this hotfix&lt;/A&gt; which is included in &lt;A href="http://support.microsoft.com/kb/945757" mce_href="http://support.microsoft.com/kb/945757"&gt;.NET 2.0 SP1&lt;/A&gt; so if you are running into this you can install SP1 for .NET Framework 2.0 to fix the problem.&lt;/P&gt;
&lt;P&gt;Have a good one,&lt;/P&gt;
&lt;P&gt;Tess&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9897988" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="Performance issues and hangs" scheme="http://blogs.msdn.com/tess/archive/tags/Performance+issues+and+hangs/default.aspx" /><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry><entry><title>Busy November, presenting at TechED Europe and Oredev</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/09/17/busy-november-presenting-at-teched-europe-and-oredev.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/09/17/busy-november-presenting-at-teched-europe-and-oredev.aspx</id><published>2009-09-17T15:13:38Z</published><updated>2009-09-17T15:13:38Z</updated><content type="html">&lt;p&gt;&lt;a href="http://www.msteched.com/europe/public/"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 5px 35px 5px 5px; display: inline; border-top: 0px; border-right: 0px" title="TechEd_Europe_Blog_SM_STD" border="0" alt="TechEd_Europe_Blog_SM_STD" align="left" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/BusyNovemberpresentingatTechEDEuropeandO_C80F/TechEd_Europe_Blog_SM_STD_3.gif" width="124" height="94" /&gt;&lt;/a&gt;    &lt;br /&gt;&lt;strong&gt;&lt;a href="http://www.microsoft.com/europe/teched/"&gt;TechED Europe&lt;/a&gt; – Berlin -&amp;#160; 9-13th of November&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;This will be the 2nd time I present at TechED. Last time I had an absolute blast and heard some really&amp;#160; good speakers.&lt;/p&gt;  &lt;p&gt;I am still working with the TechED team on exactly what type of sessions I will get, and exactly what I’ll be talking about but I’m sure it won’t surprise anybody reading this blog that there will be a lot of debugging involved:)&amp;#160; &lt;/p&gt;  &lt;p&gt;There will be lot’s of windbg and maybe some Visual Studio 2010 stuff, and of course since I’ll be presenting in the web track there will be plenty of asp.net stuff.&amp;#160; Having said that, most things I say apply to any .net application.&lt;/p&gt;  &lt;p&gt;On the speakers list, the people I am looking forward to seeing the most are &lt;a href="http://blogs.technet.com/markrussinovich/default.aspx"&gt;Mark Russinovich&lt;/a&gt; of course, Roy Osherove and my friend &lt;a href="http://blog.noop.se/"&gt;Magnus Mårtensson&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt; &lt;a href="http://www.oredev.org"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" hspace="20" alt="a" vspace="20" align="left" src="http://www.oredev.org/prod/oredev/site.nsf/shared/809132AC66E07797C12576270054B9A1/$file/BannerSpeaker12.gif" /&gt;&lt;/a&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;     &lt;br /&gt;&lt;a href="http://www.oredev.org/"&gt;OreDev&lt;/a&gt; – Malmö, Sweden – 2-6th of November      &lt;br /&gt;&lt;/strong&gt;    &lt;br /&gt;Coincidentally Magnus happens to be working for the company (dotway) that organizes Oredev. &lt;/p&gt;  &lt;p&gt;I’m really excited about Oredev this year.&amp;#160; The lineup is sooooooo good that I will have a hard time choosing what sessions to go to.&lt;/p&gt;  &lt;p&gt;The Scotts (&lt;a href="http://www.hanselman.com/blog/"&gt;Hanselman&lt;/a&gt;, &lt;a href="http://odetocode.com/Blogs/scott/"&gt;Allen&lt;/a&gt; and &lt;a href="http://codebetter.com/blogs/scott.bellware/default.aspx"&gt;Bellware&lt;/a&gt;) for sure, and it is always fun to hear what my colleague &lt;a href="http://blogs.msdn.com/johanl"&gt;Johan Lindfors&lt;/a&gt; has to say.&lt;/p&gt;  &lt;p&gt;Oredev is a pretty cool conference because they pull in sessions from many different areas so this is a perfect place to go and watch what people outside of the .NET Development field are doing.&lt;/p&gt;  &lt;p&gt;I’ll of course be talking about what I know best:)&amp;#160; Debugging, troubleshooting, Asp.Net, you know the drill.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Hope to see you all there… I’ll be on twitter @TessFerrandez (on and off) during the events so don’t be shy.&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9896302" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /></entry><entry><title>Forms authentication fails after installing IIS 7.5</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/09/16/forms-authentication-fails-after-installing-iis-7-5.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/09/16/forms-authentication-fails-after-installing-iis-7-5.aspx</id><published>2009-09-16T12:35:00Z</published><updated>2009-09-16T12:35:00Z</updated><content type="html">&lt;P&gt;I recently had a customer that just moved from Windows 2008 to Windows 2008 R2 (changing from IIS 7 to IIS 7.5) and after the move they got some weird forms authentication errors in the event log&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The problem&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;They have two applications (MyWebApp and MyLoginWebApp) where forms authentication is dealt with in MyLoginWebApp &lt;/P&gt;
&lt;DIV class=SampleCode&gt;
&lt;P&gt;&amp;lt;authentication mode="Forms"&amp;gt; &lt;BR&gt;&amp;nbsp; &amp;lt;forms name="MyAppAuth" loginUrl="/MyLoginWebApp/Default.aspx" protection="All" timeout="720" path="/" slidingExpiration="true" /&amp;gt; &lt;BR&gt;&amp;lt;/authentication&amp;gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Once the user is authenticated they are redirected back to MyWebApp but on the redirect, forms authentication fails (and logs events like the below), and redirects back to the MyLoginWebApp application.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Event ID: 1315 &lt;BR&gt;Event message: Forms authentication failed for the request &lt;BR&gt;Reason: The ticket supplied was invalid&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The two applications are setup to run in different application pools in order to avoid problems occurring in one of the apps to affect the other.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Autogenerated machine keys &lt;BR&gt;&lt;/STRONG&gt;&lt;BR&gt;Forms authentication requires a machine key to encrypt and decrypt the ticket and this has to be the same on the sending and receiving end.&amp;nbsp; You can use to specify a manually generated key or use an autogenerated one. &lt;/P&gt;
&lt;P&gt;Now, by default when using AutoGenerate machinekeys, the autogenerated machinekey is isolated per application.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;To be able to use the same autogenerated machinekey over multiple applications you need to go in to IIS Manager (on IIS7+) and in the Machine Key settings, uncheck the box for “Generate a unique key for each application”.&amp;nbsp;&amp;nbsp; If you are running IIS6, you can remove the IsolateApps keyword from the &amp;lt;MachineKey…&amp;gt; tag in Machine.Config to allow for the key to be the same across applications.&lt;/P&gt;
&lt;P&gt;If you are crossing applications, and especially if you are in a web farm scenario where you may be crossing machine boundaries, you should consider using a pre-generated Machine Key rather than an autogenerated one.&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Using a manually generated key actually worked for them, but for various reasons they wanted to use an AutoGenerated one and as this worked in IIS 7 they were curious why it didn’t work now.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Troubleshooting&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;To get to the bottom of the problem I started looking at how these autogenerated keys were stored and what could be causing the two applications to not use the same one.&lt;/P&gt;
&lt;P&gt;I found this blog post by &lt;A href="http://blog.zygonia.net/2006/10/26/ASPNET20AspnetregiisGaSwitch.aspx" mce_href="http://blog.zygonia.net/2006/10/26/ASPNET20AspnetregiisGaSwitch.aspx"&gt;Kev&lt;/A&gt; talking about exactly that and describing how the autogenkey was stored in the registry.&amp;nbsp; The blog post actually talks about the exact same issue we are seeing. In his case the reason for the failure was that if the process doesn’t have permissions to write to the registry it has to regenerate the key each time a process starts up.&lt;/P&gt;
&lt;P&gt;So just for house keeping, the registry key where the autogenerated key is stored is:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\2.0.50727.0\AutoGenKeys\S-1-5-21-3520846933-1734744541-1252751799-1013&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This seemed to fit our problem pretty well.&amp;nbsp; When you are separating the apps out into different application pools they run in different processes, and if they didn’t have enough permissions to write the key it would be autogenerated at startup (different ones for the different application pools).&lt;/P&gt;
&lt;P&gt;The problem was that I could reproduce this, and I could see the autogen keys in my registry so I knew that we didn’t have trouble writing it.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;While looking at this though, I discovered that my two application pools were running under different users (for example the user for the DefaultAppPool was DefaultAppPool and the user for my TestAppPool was TestAppPool).&amp;nbsp; &lt;BR&gt;&lt;BR&gt;Looking back at the registry key, it contains a SID, so the autogenkey is stored on a per user bases, i.e. in our case, since the two processes are running under different users they would have different autogen keys, which explains why we are seeing issues here.&lt;/P&gt;
&lt;P&gt;It turns out that there was a change between 7 and 7.5 that Dave wrote about &lt;A href="http://blogs.iis.net/davcox/archive/2009/08/12/what-is-my-iis-code-running-as.aspx" mce_href="http://blogs.iis.net/davcox/archive/2009/08/12/what-is-my-iis-code-running-as.aspx"&gt;here&lt;/A&gt; where they changed the default identity of the application pool from Network Service to an automatically generated AppPool identity.&amp;nbsp; So this is why there was a difference between 7 and 7.5 when using autogen keys.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The solution&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The solution here is rather obvious once you know the background, either you manually generate a key, rather than using an autogen one, or you change the identity of the application pool to the same user for each app pools.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Have fun,&lt;/P&gt;
&lt;P&gt;Tess&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9895771" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /></entry><entry><title>First step in troubleshooting complex issues: Define and scope your issue properly</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/09/09/first-step-in-troubleshooting-complex-issues-define-and-scope-your-issue-properly.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/09/09/first-step-in-troubleshooting-complex-issues-define-and-scope-your-issue-properly.aspx</id><published>2009-09-09T14:21:46Z</published><updated>2009-09-09T14:21:46Z</updated><content type="html">&lt;p&gt;Is it a plane, is it a bird, is it a UFO?&lt;/p&gt;  &lt;p&gt;Before you can delve into any kind of troubleshooting of an issue you need to thoroughly define it.&amp;#160; If you don’t you’ll probably end up spending a lot of time randomly gathering and looking at data that is probably not even relevant to the issue at hand.&amp;#160; More importantly, how do you even know that your problem is fixed if you don’t have a good definition of the problem?&lt;/p&gt;  &lt;p&gt;This might sound like common sense, but having worked with troubleshooting the better part of the last 10 years I can tell you that it is extremely common that people start looking at data before really understanding the problem.&amp;#160; More often than not this is because people are stressed and want to fix the problem fast, or maybe because the problem space is unknown to them so they have difficulties defining what information or details are important.&amp;#160; Sometimes symptoms are even contradictory which makes it even more difficult to troubleshoot something, as you don’t know if you can trust the data.&lt;/p&gt;  &lt;p&gt;I don’t have a silver bullet recipe for success but I wanted to share how I approach an issue (in a pretty generic way) and I welcome any and all input that you might have on the topic as good scoping/problem definitions is something that is often a topic of discussion at my workplace. &lt;/p&gt;  &lt;p&gt;What I do know for a fact is that a lot of times, the issues where we don’t have a proper problem definition that is agreed between all parties, tend to take a lot longer to resolve than the ones they do.&amp;#160; Similar to if you have a software project where you haven’t spent proper time on working with the customer on their requirements.&amp;#160; And in the end, if you had a good agreement between all parties, you don’t end up resolving the wrong problem.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;My 9 questions for a pretty thorough problem description&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;When I call up a customer to start working on an issue I am generally looking for them to answer 9 questions in their own words.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1. What is happening?      &lt;br /&gt;2. What did you expect to happen?      &lt;br /&gt;3. When is it happening?       &lt;br /&gt;4. When did it start happening?       &lt;br /&gt;5. How does this problem affect you?      &lt;br /&gt;6. What do you think the problem is? and what data are you basing this on?      &lt;br /&gt;7. What have you tried so far?      &lt;br /&gt;8. What is the expected resolution?      &lt;br /&gt;9. Is there anything that would prohibit certain troubleshooting steps or solutions?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;All of these questions are pretty open ended and a lot of the questions can’t be answered on the first pass before gathering more data, but at least then we know what data we need to gather to continue. &lt;/p&gt;  &lt;p&gt;Throughout the process of defining the issue, I usually also try to assess the reliability of the information I get so that I know what is a known fact and what is hearsay to avoid spending too much time on things that may not be relevant.&lt;/p&gt;  &lt;p&gt;If you’re troubleshooting an issue by yourself, it might be worthwhile pairing up with someone to explain the problem since a lot of things tend to get clearer if you say them out loud and have to explain them.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;What am I really looking for when asking these questions?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;1. What is happening&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Let’s say we have a problem where we are experiencing a “hang” in an ASP.NET application on a production server, this would be what I am looking for or not looking for in my definition.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Bad answer: Occasionally our IIS server just hangs.&lt;/em&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;This is a pretty common answer, but in reality it says nothing about what is going on.&amp;#160; The words hang, crash or memory leak for example mean a lot of different things to different people.&amp;#160; &lt;/p&gt;    &lt;p&gt;A crash for example might mean anything from “we just get blank pages”, user gets a “service unavailable”, there is a “stopped unexpectedly” log in the eventlog, user sees a “NullReferenceException” page in the browser, or really anything where the application is not doing what it is supposed to.&lt;/p&gt;    &lt;p&gt;A hang, could be anything from a “crash”, to a particular page responding in 5 seconds rather than 2 seconds, or something where the pages stop responding completely, leaving the user with a spinning cursor, or a timeout, or a complete system freeze.&lt;/p&gt;    &lt;p&gt;Memory leaks are my favorite ones, people tend to use “memory leak” as the bucket for cases where “we don’t know what is going on so we must have a memory leak”.&amp;#160; Even in the cases where there are actually memory problems, there is a big variation in the symptoms, like anything from “the process grows from 200MB private bytes to 1 GB in 20 minutes” to outofmemoryexceptions to “watching the process in taskmanager i see some memory growth”.&lt;/p&gt;    &lt;p&gt;In either case, the more details you can get, the better off you are, and if it is not detailed enough you need to set up an action to get more data before starting to troubleshoot.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;em&gt;Better answer:&lt;/em&gt;&amp;#160; &lt;em&gt;Once or twice a day over the last two weeks we have gotten reports from customers that the login page is not responding.&amp;#160; Eventually if they wait long enough the page will time out.&amp;#160; We have confirmed this behavior by logging in at the time of the failure, but all other pages seem to be working well during the problem period.&amp;#160;&amp;#160; The problem persists until we restart IIS.&amp;#160; We have not seen any events in the event log matching the time of the failure. &lt;/em&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Note:&amp;#160; There are a couple of things worth mentioning here.&amp;#160; The timing of once or twice a day is important, as once we resolve the issue, we can be fairly sure it is resolved if it doesn’t happen for two days for example.&amp;#160;&amp;#160; The fact that it is verified by someone in-house makes the symptom pretty reliable. The fact that the problem persists until an IISReset is issued tells us a couple of things.&amp;#160; 1. we have a window for getting memory dumps before recycling, 2. there is a good chance the contention exists in the app since it is not persistent after a recycle.&amp;#160; And finally, the fact that no other pages are affected give us a very defined area to look at.&amp;#160; &lt;/p&gt;    &lt;p&gt;Of course this is just a random issue, but you get the idea of how much better we are off with this answer than the first answer.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;2. What did you expect to happen&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;This is a question that is often overlooked because the answer is often assumed, but the reality is not as simple as that.&lt;/p&gt;  &lt;p&gt;If we take a memory issue for example, to understand what is considered bad memory patterns, we need to understand what the memory usage is in testing for x number of users, what the baseline memory usage is and how much memory we are expecting to store in session/cache etc. per user.&lt;/p&gt;  &lt;p&gt;For a performance issue we need to have a baseline response time.&amp;#160; Even if the problem we are trying to resolve is that pages are timing out, it is important to know if the expected response time for the page is 5 seconds or a few milliseconds, and also if the application has been stress tested and shown those results during testing.&lt;/p&gt;  &lt;p&gt;In a crash scenario where you are looking at error events in the event log it is also nice to note down that you are expecting for the process to recycle every 24 hrs for example based on recycling reasons, so that you know that eventlogs relating to that can be discarded.&lt;/p&gt;  &lt;p&gt;In the best of cases we would have a solid set of performance logs, event logs and iis logs from normal operation to compare to once we gather for the faulty state.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;3. When is it happening?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;A solid repro scenario is of course optimal, but with production type issues this is seldom the case.&amp;#160;&amp;#160; Things that I am looking for here are.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;How often the problem reproduces (eg. once or twice a day in the above example)&lt;/li&gt;    &lt;li&gt;Do we know what actions people take, i.e. it happens when they try to log in?&lt;/li&gt;    &lt;li&gt;Do we know if it is confined to one server, one application, one page, one action?&lt;/li&gt;    &lt;li&gt;Do we know if it is reproducible in test?&lt;/li&gt;    &lt;li&gt;Is it happening only for certain users?&lt;/li&gt;    &lt;li&gt;Is it happening only under load?&lt;/li&gt;    &lt;li&gt;Does it only happen when memory usage is high, or when CPU usage is over 80%?&lt;/li&gt;    &lt;li&gt;Does it always happen at 8 am when the first people in the office start logging in?&lt;/li&gt;    &lt;li&gt;etc. etc.&amp;#160; any and all conditions relating to the issue are interesting.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;4. When did it start happening?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;If the application has been working well for a while and suddenly starts behaving weird, it stands to reason that perhaps something that happened around that time could have affected it. &lt;/p&gt;  &lt;p&gt;Often though there is a difference between the time when it started happening and when it was first discovered, so make sure to verify the time that it started happening against any available data (eventlogs, iislogs, performance logs etc.) that you might have.&lt;/p&gt;  &lt;p&gt;All in all, knowing when it started happening is often one of the most important clues to finding root cause.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;5. How does this problem affect you?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;When I work on an issue, I like to know what kind of impact the problem has on the customer and the users of the system.&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;The reason I ask about this is because if a problem causes users not to be able to log in for example, and this is a critical application for the business, obviously we should be starting by finding a temporary fix, rather than going through root cause analysis, or maybe starting with a temporary fix first (like recycling when memory reaches 600 MB if the problem is a memory leak, to avoid an unexpected crash), and then preparing for root cause analysis.&lt;/p&gt;  &lt;p&gt;It also tells me a little bit about the priority that troubleshooting is going to get.&amp;#160; If the issue is very severe, maybe it is ok to perform some troubleshooting actions that have a lot of impact on the system, if it is going to help us find the problem faster.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;6. What do you think the problem is? and what data are you basing this on?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This is especially interesting if you come in as an external troubleshooter, as you get a lot of insight into known problem areas of the application by asking what they think the problem might be. &lt;/p&gt;  &lt;p&gt;There is a temptation to follow down the path of what is already guessed because it often sounds very plausible, but when I look at a problem I try to keep a very open mind to avoid getting stuck in a tunnel.&lt;/p&gt;  &lt;p&gt;If someone believes that the problem is “x” then oftentimes, because of how our minds work, we tend to look at the data from that direction, even if it doesn’t fit. Part #2 of this question is what data you are basing your theory on?&amp;#160; I try to look at that data with fresh eyes, to see if it &lt;strong&gt;really&lt;/strong&gt; collaborates the theory or if there are some holes in it.&amp;#160;&amp;#160; To be honest, if a person comes to me with an issue and already has a theory, the first thing i try to do is to disprove it. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;7. What have you tried so far?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This question serves two purposes.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1. Finding out what has been done so we don’t need to re-invent the wheel.&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;2. Finding out the results of those actions as it gives us more data about the problem.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Keep in mind here as well that reliability is important.&amp;#160; If something was presumably done but there is no documentation of it or the results, it is probably worthwhile re-doing it, depending on how complex the task was.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;8. What is the expected resolution?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This might sound like a repeat of question 2 (What did you expect to happen), but it is very different.&lt;/p&gt;  &lt;p&gt;An expected resolution might be to “avoid the crash” which you can do by preemptive recycling, separating the app into a different application pool, moving to 64-bit, reverting back to a previous build etc. &lt;/p&gt;  &lt;p&gt;Another expected resolution might be to “find the root cause to avoid that it happens again”. &lt;/p&gt;  &lt;p&gt;And a third may be, “if we get the pages to consistently respond in less than 5 seconds under load we are good”. &lt;/p&gt;  &lt;p&gt;Defining the expected resolution is crucial as this is what you will measure and verify the solution against to determine when you are done troubleshooting.&amp;#160; If you don’t have this, how will you know when you are done?&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;This expected resolution, just like requirements in a software project, should also be agreed upon so that all involved parties work against the same goal.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;9. Is there anything that would prohibit certain troubleshooting steps or solutions?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Knowing the limitations of data gathering or certain solutions both determine what actions you can take and change the expectations of what can be achieved.&amp;#160; &lt;/p&gt;  &lt;p&gt;On this question I would expect answers like, we can not install any tools on the server without going through a process of 10 change requests, or we can reproduce this on a test machine so you can live debug if you need to.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Summarizing everything&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Once I have all the facts from the questions above I usually sit down and summarize everything in a format that looks something like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Problem description:     &lt;br /&gt;===========================      &lt;br /&gt;…      &lt;br /&gt;Expected resolution:      &lt;br /&gt;===========================      &lt;br /&gt;…      &lt;br /&gt;Troubleshooting done:      &lt;br /&gt;============================      &lt;br /&gt;…      &lt;br /&gt;Next steps:      &lt;br /&gt;===========================      &lt;br /&gt;…      &lt;br /&gt;Timeline for next steps:      &lt;br /&gt;===========================      &lt;br /&gt;…&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is a format I use to document problems throughout the course of the troubleshooting, updating it as the troubleshooting progresses and this is a format that we use both in our support cases and our bug reports in different variations.&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;It has proven to be a pretty effective way to keep tabs on issues especially when we have to collaborate on a case or hand over an issue to someone else for some reason or another. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Happy troubleshooting,&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9893034" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="Memory issues" scheme="http://blogs.msdn.com/tess/archive/tags/Memory+issues/default.aspx" /><category term="Performance issues and hangs" scheme="http://blogs.msdn.com/tess/archive/tags/Performance+issues+and+hangs/default.aspx" /><category term="Crash scenarios" scheme="http://blogs.msdn.com/tess/archive/tags/Crash+scenarios/default.aspx" /><category term="General debugging tidbits" scheme="http://blogs.msdn.com/tess/archive/tags/General+debugging+tidbits/default.aspx" /><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /></entry><entry><title>How can I make you learn and benefit from my Blog? and how can I learn from you?</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/tess/archive/2009/08/17/how-can-i-make-you-learn-and-benefit-from-my-blog-and-how-can-i-learn-from-you.aspx" /><id>http://blogs.msdn.com/tess/archive/2009/08/17/how-can-i-make-you-learn-and-benefit-from-my-blog-and-how-can-i-learn-from-you.aspx</id><published>2009-08-17T13:43:21Z</published><updated>2009-08-17T13:43:21Z</updated><content type="html">&lt;p&gt;Summer is almost over and a new season of heavy work is beginning.&amp;#160; I wanted to take this opportunity to start on a new page and make sure that I’m spending my cycles doing the right things.&amp;#160; &lt;/p&gt;  &lt;p&gt;I’ve been blogging for almost 3 years now and throughout the blogs life I’ve been blogging pretty much the same way, trying to show examples of where me and fellow developers have gotten into situations that have caused crashes, memory leaks, exceptions, hangs etc., so that we can all learn from the situations and avoid them. &lt;/p&gt;  &lt;p&gt;Throughout the 3 years I have gotten a lot of comments saying that posts have helped developers, but I have also gotten more private comments saying that what I am talking about lies so far out of their realms that they don’t understand half of what I am saying.&amp;#160; Some of these comments have come from people that I know and respect and that I know are extremely proficient developers, which makes me think that maybe I am not explaining things in a very understandable or approachable way.&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;I have also noticed that people tend to send me private emails rather than comment on the blog, maybe because people feel a bit too intimidated by post-mortem debugging to comment directly on the blog since the topic is a bit low-level. Maybe I am all wrong and that is not at all why people email me rather than comment:)&lt;/p&gt;  &lt;p&gt;Either way, since this has been bugging me for a while, I wanted to let you know how I look at my blog and what I want it to be, and I also wanted to solicit your ideas on how to make it more that way.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;My philosophy with the blog&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I work as an ASP.NET Support Escalation Engineer which means that my job is to help developers solve these types of issues.&amp;#160; When I can help them resolve their issues that makes both me and them happy.&amp;#160;&amp;#160; In reality though they would probably be a lot happier if they could resolve their own issues and didn’t have to call, or even more happy if they didn’t have these issues in the first place. &lt;/p&gt;  &lt;p&gt;With all that, my goal has always been to try to avoid that people need to call support, so effectively my goal is to make my job obsolete:).&amp;#160; I realize that people will always run into pitfalls so I set up this blog to teach people debugging and make people more aware about the internals of asp.net and the CLR, and to learn from each other.&lt;/p&gt;  &lt;p&gt;I want people to be less intimidated by debugging and see that it is in fact something that we can all do, something that is useful to all developers and something that is not as difficult or far out there as it may seem at first look.&lt;/p&gt;  &lt;p&gt;I want people to ask lots of questions, or comment on things that they want to know more about, don’t understand or don’t agree with.&amp;#160; The more such comments and questions there are, the more I and others can learn from them.&amp;#160; In a perfect world, this would be a nice debugging community where we all learn from each other. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;My ask from you&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I would like to learn from you what ideas you have around how I can accomplish this goal better.&amp;#160; &lt;/p&gt;  &lt;p&gt;How many of you just glance at the posts and think “hmm, probably interesting for someone who is deep down into debugging but I’ll never use this”?&amp;#160; How many of you really read them and learn something from them?&lt;/p&gt;  &lt;p&gt;Are the posts too long, too short, too deep, not deep enough, too boring, too many stupid jokes?&lt;/p&gt;  &lt;p&gt;What makes you shy away from a post and what makes you want to learn more?&amp;#160; &lt;/p&gt;  &lt;p&gt;How can I make things more applicable to the world you live in?&lt;/p&gt;  &lt;p&gt;What do you want to see more or less of?&lt;/p&gt;  &lt;p&gt;How can I help you so that you can apply more of what I am talking about to your day to day job?&lt;/p&gt;  &lt;p&gt;Do you want me to mix up the debugging posts more with some lighter posts about other topics?&amp;#160; If so, what would you be interested in?&amp;#160; &lt;/p&gt;  &lt;p&gt;Feel free to be as candid as you can:)&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Have fun,   &lt;br /&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9872188" width="1" height="1"&gt;</content><author><name>Tess</name><uri>http://blogs.msdn.com/members/Tess.aspx</uri></author><category term="ASP.NET" scheme="http://blogs.msdn.com/tess/archive/tags/ASP.NET/default.aspx" /><category term="Debugging" scheme="http://blogs.msdn.com/tess/archive/tags/Debugging/default.aspx" /></entry></feed>