What are those empty exception objects on your heap?

Friday, February 10, 2012

This week I’ve been busy debugging a memory dump of a Windows service with WinDBG. For people who have never heard of it, this is one of the most powerful debuggers out there. It’s far more powerful then the Visual Studio debugger because it let’s you do low level stuff. WinDBG is part of the Debugging Tools for Windows. By default it’s designed for debugging unmanaged code but with the use of some extensions (SOS, Pscor2), you can debug managed code as well. There are a lots of tutorials on the web which help you get started.

Now back to subject. During my debugging of the memory dump, I searched for possible occurred exceptions which must be located on the heap. So to check all types with the name Exception in it, you can issue the command: 

!dumpheap –type Exception

HeapException

 

This gives back eleven objects on the heap which has the name Exception in it. Now the first two classes and the sixth are false positives. These aren’t real exceptions objects. But the other ones are in fact inheriting from System.Exception. Now this surprised me because I didn’t notice any thrown exceptions in the exception log our Windows service. So I got curious and filtered on the System.StackOverflowException with the same command as before. 

!dumpheap –type System.StackOverflowException 

HeapStackOverflow

This tells me the exact address on the heap. So we could check the contents of it. Now because we know it’s a exception we can use the following command to show it contents. 

!pe 0102106c

(pe stands for printexception) 

PEStackOverflow

This is not the result I expected. I wanted it to show me it’s message and stacktrace information so I could locate the problem at hand. All the data is empty. Now it turns out this goes for the other exception objects on my heap as well. There must be a reason why they are standing there using my memory and of course there is.

Now for the following three exceptions the answer is pretty simple. 

System.ExecutionEngineException

System.StackOverflowException

System.OutOfMemoryException

Most of the time when one of these exceptions is thrown the system will be in a state that it can’t create them. In this scenario it will use the pre-allocated objects. Pretty smart if you tell me. Now we have two, yes two empty System.Threading.ThreadAbortExceptions left. I could not find anything about this on the net so I decided to call in StackOverflow. It turns out that the answer is found in the source code of the CLR.

From clr/src/vm/clrex.cpp, CLRException::GetThrowable(): 

// If creating a normal ThreadAbortException fails, due to OOM or StackOverflow, 
// use a pre-created one. 
// We do not won't to change a ThreadAbortException into OOM or StackOverflow, because 
// it will cause recursive call when escalation policy is on: 
// Creating ThreadAbortException fails, we throw OOM.  Escalation leads to ThreadAbort. 
// The cycle repeats. 
throwable = GetPreallocatedThreadAbortException(); 

Same file, CLRException::GetPreallocatedRudeThreadAbortException() method: 

// When we are hosted, we pre-create this exception. 
// This function should be called only if the exception has been created. 
_ASSERTE(g_pPreallocatedRudeThreadAbortException); 
return ObjectFromHandle(g_pPreallocatedRudeThreadAbortException); 

This code snippets are responsible for pre-allocating the two System.Threading.ThreadAbortExceptions we see on the heap. The comments of the first snippet says it all. The second one is more difficult but is used for what they call a rude abort. A rude abort can only be raised by the CLR itself. You can read more on this subject over here and here.

To conclude, it didn’t helped me solving the actual problem but it sure gave me a better insight in what and why the CLR does certain things and last but not least it was fun to find out.

Tags: , ,
Filed Under: Programming, Technology
Comments are closed