Tagged: Exception

Debugging Managed Memory, Handle, GCHandle Leaks, Exceptions and Fragmentation with WinDbg

Assuming you already have WinDbg installed (X86 bit for your 32 bit applications, and the appropriate 64 edition for your 64 bit applications) , after startup in administration mode, you’ll want to:

1) Attach to your application process or run directly from WinDbg

2) For .Net 4.0 and above run .loadby sos clr or .loadby sos mscorwks for .Net 2.0

3) Update your symbol path so you have all the debug information that you’ll need e.g. ” *srv*c:\symbols*http://msdl.microsoft.com/downloads/symbols* “. You’ll also want to browse and add the location of the pdb files for you application.

4) Just like the VS debugger, press F5 to resume execution and CTRL+BREAK to break at any time.

5) In WinDbg, run !analyze -v (to force a load of the symbols – you’ll only need to do this the first time)

6) At any point in time when you’re at a break point you can

  •  View the CLR stack with !CLRstack
  •  View the managed threads with !Threads
  •  View combined managed and unmanaged call stack with !dumpstack
  •  View unmanaged code stack kL

Fore more useful commands check David Douglass’s SOS Cheat Sheet or Alejandro Campos Magencio SOS Cheat Sheet

Managed memory leak

Exceptions

  • For heap information on a particular type of Exception run !DumpHeap -type Exception
  • To break on all CLR exceptions run sxe clr
  • To view the last thrown exception run !pe

For further details check Alejandro Campos Magencio’s Managed Debugging with WinDbg article

Handle leaks

  • Turn on handle tracing with !htrace -enable
  • Check handles with !handles
  • Check specific handle stats with !handles <address>

For further details check Toby Opferman’s Handle leaks article

GChandle leaks

  • For stats on GCHandles run !GCHandles
  • For stats on what could potentially be a GCHandle leak, run !GCHandleLeaks

For further details check Alejandro Campos Magencio’s Managed Debugging with WinDbg article

Memory Fragmentation
Out of memory exceptions might also indicate memory fragmentation.

  • !finalizequeue – to get details on the finalization queue and compare two results to see if there are any glaring increases in the objects. For example a huge jump in generation 2 objects but 0 objects ready to be finalized.
  • After that you’ll want to look into the object that’s in the finalization queue using !do <address>. You can obtain the object addresses by listing out the dwords (using dd <starting address> <ending address>). For example, using the ending address of the 2nd generation minus the size of the object in question as the starting address, and the end of the 2nd generation as the ending address). For more details on this visit Shreous
  • !gcroot -nostacks <object memory address> – To see the references for the object in question

Finally for a list of the extension commands: SOS Debugging Extensions.

Catching exceptions and locks

Locks and exceptions do not mix <Eric Lippert’s Blog>

In summary, you want to

  1. Do as little as possible in the body of a lock.
  2. Even though it’s difficult and for many cases next to impossible, return your application to a pristine state. i.e.  “carefully implement the bodies of locks that do mutations so that in the event of an exception, the mutated resource is rolled back to a pristine state before the lock is released.”
  3. Don’t abort threads for the reason of leaving you application in an inconsistent state (unrecoverable). The thread should wait for a synch object and then return from the running methods in a consistent manner.

WCF async callback exception – safe handle has been closed

It’s isn’t a good idea to close a handle returned from an asynchronous WCF handle ;). ….just handle the closing of the proxy; unless you enjoy catastrophically bringing down .NET processes.

Unhandled Exception: System.Runtime.CallbackException: Async Callback threw an exception. —> System.ObjectDisposedException: Safe handle has been closed
at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)
at Microsoft.Win32.Win32Native.SetEvent(SafeWaitHandle handle)
at System.Threading.EventWaitHandle.Set()
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously, Exception exception)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.FinishEnsureOpen(IAsyncResult result, Boolean completedSynchronously)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.EnsureOpenCallback(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
— End of inner exception stack trace —

WCF server side exception handling best practice

If the service calls an object or if the service itself throws an exception it can bring down the service, so it’s important to handle them. Rather than error masking with try catch statements, with WCF it’s best to make use of the IErrorHandler.

Simply implement the interface on your service contract and then you’ll be able to mask and report errors or turn the exceptions into faults. Details can be found here.