This afternoon I was working on some code that I don’t have the developer around for. Part of the app is a windows service which fires up a server to listen for incoming connections. I could see from the log file that we were getting an AddressNotAvailable exception, but I didn’t understand why. I had a feeling it was a misset configuration parameter, but I needed more information.
To debug this, we have two challenges. First is that debugging startup code in .NET is just a tidbit tricky since you won’t get to a stopping point to load sos before the exception happens. The second is that Windows Services are a little difficult to debug as well, and require some more in-depth mojo.
There was a third issue at play as well. This code was reporting the exception – and then swallowing it. This means that we’d only ever get a first chance exception, so we have to be able to break on those.
So how do we debug it? First, we have to setup the service so that when it starts, it also starts WinDBG. We can’t just point to the service executable. KB 824344 is your friend here. Basically you set a registry key which fires up the debugger when that executable starts. You’ll also want to follow step 3 in that article to increase the time Windows waits for the service to start up – I used 100000 milliseconds.
Now, when you click Start, WinDBG will pop-up. When it does, it will immediately breakpoint into the application. You would think at this point you could do a ".loadby sos mscorwks" but you can’t – none of the .NET libraries have been loaded yet. Basically we have broken in at the start of the PE. So we need to tell WinDBG to break as soon as the .NET libraries have loaded, but before our app gets going. Tess (as usual) comes to the rescue with this article which explains how to do it. Basically, you just run an "sxe ld:mscorlib" which says to break whenever a library called mscorlib is loaded. When it does, you can then do a ".loadby sos mscorwks" to get sos loaded.
Remember that I said there was a third issue, and that was that we only got first chance exceptions. To break on First-Chance exceptions, go to Debug->Event Filters while WinDBG is broken in. Then click on the "CLR exception" event, and choose enabled. There’s a command line way too – "sxe clr". Note that you’ll need to make sure you do this before you let the application continue after the .NET library load.
And viola, now WinDBG will break in at each exception. Since you have sos loaded, you can do a !printexception to see what the exception is. For me, once I found the exception, I did a !dso to see the stack objects, and investigated the IPEndPoint objects on the stack until I found the one that had a funky IP. Armed with that, I was able to find the setting in the config file and change it to the local IP, and my server was happy again.