Monday, May 17, 2010

Managed Debugging Assistants (MDAs)

In this post I will talk about a useful debugging technique called Managed Debugging Assistants (MDAs). MSDN has very detailed documentation on this subject and you can find it here. Although MDAs are not essential for everyday debugging, they might prove useful in many cases. They are not extremely well-known technique and are not easily noticeable feature in Visual Studio. As we will see later in this post, you don't need to have Visual Studio installed in order to use MDAs.

MDAs work with CLR to provide notifications (while application is running) about some interesting events that in most cases represent application defects. These defects are not easily noticeable without MDAs. For example, most likely you wouldn't notice them while doing ordinary debugging. This is because these defects do not have to cause crashes or similar visible effects. But generally they are serious issues and once in a while they might really result in crashes, resource leaks or similar.

There is a long list of MDAs supported by CLR. Basically, each MDA is a problematic scenario that can be recognized and reported. Some of the examples are: AsynchronousThreadAbort which occurs when some thread tries to asynchronously abort another thread, LoadFromContext which occurs when application tries to load an assembly into Load From Context, StreamWriterBufferedDataLost which occurs when StreamWriter gets destroyed before all data is flushed, etc... You can find the full list at MSDN page linked above. Also you might view this list in Visual Studio inside of Exceptions Dialog (activated by Ctrl+Alt+E).

How To Use MDAs?

If you are using Visual Studio, the only thing you need to do is to open the dialog shown above and select MDAs you would like to use. When you run problematic application, you will see that MDA notification looks very similar to dialog we see when we hit an unhandled exception.

If we don't have Visual Studio installed we will have to do several things manually. First of all, we will have to use notepad :-) ... to write the following program:

Basically, main thread creates new thread and then asynchronously aborts it with Abort method. This method starts thread termination process by throwing ThreadAbortedException inside the thread. After that we synchronously wait for thread to terminate by calling Join method, but the termination itself was asynchronous.

Asynchronous thread termination process can be dangerous for many reasons. In the example above it doesn't cause any unwanted effects, but in general it can lead to probleems such as resource leaks. This can happen because code that frees these resources won't be executed due to abort operation.

Now let's imagine that this is a very complex app and we are suspecting that it might have problems with asynchronous thread aborts. How can we detect them?
First of all we will have to enable MDAs. They can be enabled in two different ways:
  • By adding string value (Value Name=MDA, Value Data=1) to registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework.
  • By setting environment variable COMPLUS_MDA to 1.
We can disable MDAs analogously by setting the registry value \ environment variable to 0.

In this way we are enabling MDAs globally, but in order to get MDA notifications for some specific application we will have to do one more thing. We need to create an MDA configuration file for that specific application. We get the name of this file by appending .mda.config to the name of executable. (If the name of executable is Program.exe, then the name of its configuration file should be Program.exe.mda.config). This file is in xml format and can be used to enable and optionally configure specific MDAs. The file has to be placed next to executable. In our case, here is how the configuration file would look like:

Inside the assistants tag we place the names of MDAs we would like to use. We can put as many MDAs as we want, but their names have to be alphabetically sorted as in this example:

Now that we enabled MDAs, and have both application and configuration file we can try to run the application. This is what we will see:

Dialog informs us that application threw an unhandled exception and offers us to break into debugger and further investigate the problem. In this case we are using VS Just-In-Time Debugger, but you can use any debugger you want.

MDAs usually offer additional information. For example, asynchronousThreadAbort MDA gives us the IDs of aborted thread and the thread that performed the abort operation.

The best way to further learn about MDAs is to go to the MSDN, read through the list of all existing MDAs and see which ones might be the most useful ones for your needs.

No comments: