Performance Issue Caused by Crashed Finalizer Thread

 

Customer had a newly developed .NET web application hosted in IIS 6. They recently experienced some performance issues inc. slow response, high memory consumption etc. We did a first tier analysis and decided to collect IIS crash dump. After a long monitoring, we got the 2nd chance process crash dump and there the story starts from.

First and foremost, I found the .NET exception generated when GC did object finalization:

 # ChildEBP RetAddr

00 01e5f9d8 79f071ac kernel32!RaiseException+0x53

01 01e5fa38 7a10733d mscorwks!RaiseTheExceptionInternalOnly+0x2a8

0b 01e5fda8 79fb99d6 mscorwks!WKS::FinalizeAllObjects+0x56

0c 01e5fdc0 79ef3207 mscorwks!WKS::GCHeap::FinalizerThreadWorker+0xe7

0d 01e5fdd4 79ef31a3 mscorwks!ManagedThreadBase_DispatchInner+0x4f

0e 01e5fe68 79ef30c3 mscorwks!ManagedThreadBase_DispatchMiddle+0xb1

14 01e5ffec 00000000 kernel32!BaseThreadStart+0x34

 

Then dumped the object stack and there are several exception objects with the same exception type “NullReferenceException” and the same message “Object variable or With block variable not set”. Tried to print the exception out which could possibly show us the call stack. However, it doesn’t work

0:012> !PrintException 3c8e19f0

Exception object: 3c8e19f0

Exception type: System.NullReferenceException

Message: Object variable or With block variable not set.

InnerException: <none>

StackTrace (generated):

<none>

StackTraceString: <none>

HResult: 80004003

Then I suddenly recalled that customer specially complained that the memory consumption is quite huge while I also found the crash dump size is around 1G. Quite abnormal! Plus the NullReferenceException occurred in finalizing thread, I turned around to check the finalize/dispose source code.

It turned out that CU had managed and unmanaged objects/components called in his application and he realized his own Dispose() function but didn’t suppress finalization which would let the finalization code for the object to execute a second time. Thus, NullReferenceException might occur as the object had been disposed.

Solution:

========

Added “GC.SupressFinalize(this)”in Dispose().

Reference:

Implementing Finalize and Dispose to Clean Up Unmanaged Resources

https://msdn.microsoft.com/en-us/library/b1yfkh5e(vs.71).aspx

Clearing up some confusion over finalization and other areas in GC

https://blogs.msdn.com/maoni/archive/2004/11/04/252697.aspx

Regards,

Yawei Wang