More on this WCF issue

This week I’ve been spending some more time on this WCF issue I’ve blogged about before. Unfortunately I still don’t have a solution for the problem, and I doubt that I will ever find one. However, I did find some interesting things I thought I should blog about.

I found out that the bug isn’t in the actual serialization process, but rather in the generation of the code that is supposed to do the actual serialization. WCF’s DataContractSerializer generates code on the fly to serialize and deserialize objects according to a specified data contract. The generated code is then called as a sort of anonymous delegate to perform the actual serialization or deserialization.

In the code that gets generated, serializing a nullable field is done by calling a function on the internal XmlObjectSerializerWriteContext class in the System.Runtime.Serialization namespace. This function is called GetHasValue which takes a generic type parameter T and a parameter of type T?, or a Nullable. The function is static and it simply calls the HasValue property on the provided argument and returns the result.

A reference to this method is acquired using reflection, simply by calling the GetMethod function on a typeof(XmlObjectSerializerWriterContext). Sometimes however, this doesn’t work and it returns null. This null reference is then passed to the MakeGenericMethod function which goes all the way down to the CLR which then fails because it is trying to dereference a null pointer.

What I haven’t been able to figure out so far is why getting a reference to this static GetHasValue function sometimes fails and sometimes doesn’t. There doesn’t seem to be any pattern in when it fails and when it doesn’t. I thought it might have something to do with the worker process unloading DLL’s when the application pool is being recycled, but it’s difficult to reproduce this behavior.

Here is a stack trace of when the problem occurs:

mscorwks!MethodDesc::GetMethodTable+0x12  
mscorwks!MethodDesc::StripMethodInstantiation+0x8  
mscorwks!RuntimeMethodHandle::StripMethodInstantiation+0xbd  
mscorlib_ni!System.RuntimeMethodHandle.StripMethodInstantiation()+0x6  
mscorlib_ni!System.Reflection.RuntimeMethodInfo.Equals(System.Object)+0x64  
mscorlib_ni!System.Reflection.CerHashtable`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].Insert(System.__Canon[], System.__Canon[], Int32 ByRef, System.__Canon, System.__Canon)+0x9e  
mscorlib_ni!System.Reflection.CerHashtable`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].Preallocate(Int32)+0x10e  
mscorlib_ni!System.RuntimeType+RuntimeTypeCache.GetGenericMethodInfo(System.RuntimeMethodHandle)+0xef  
mscorlib_ni!System.RuntimeType.GetMethodBase(System.RuntimeTypeHandle, System.RuntimeMethodHandle)+0x2a3490  
mscorlib_ni!System.Reflection.RuntimeMethodInfo.MakeGenericMethod(System.Type[])+0x156  
System_Runtime_Serialization_ni!System.Runtime.Serialization.XmlFormatWriterGenerator.UnwrapNullableObject(System.Reflection.Emit.LocalBuilder)+0x1cb  
System_Runtime_Serialization_ni!System.Runtime.Serialization.XmlFormatWriterGenerator.WriteValue(System.Reflection.Emit.LocalBuilder, Boolean)+0x6f287  
System_Runtime_Serialization_ni!System.Runtime.Serialization.XmlFormatWriterGenerator.WriteMembers(System.Runtime.Serialization.ClassDataContract, System.Reflection.Emit.LocalBuilder, System.Runtime.Serialization.ClassDataContract)+0x28d  
System_Runtime_Serialization_ni!System.Runtime.Serialization.XmlFormatWriterGenerator.WriteClass(System.Runtime.Serialization.ClassDataContract)+0x6f27b  
System_Runtime_Serialization_ni!System.Runtime.Serialization.XmlFormatWriterGenerator.GenerateClassWriter(System.Runtime.Serialization.ClassDataContract)+0x67  
System_Runtime_Serialization_ni!System.Runtime.Serialization.ClassDataContract.get_XmlFormatWriterDelegate()+0x50  
System_Runtime_Serialization_ni!System.Runtime.Serialization.ClassDataContract.WriteXmlValue(System.Runtime.Serialization.XmlWriterDelegator, System.Object, System.Runtime.Serialization.XmlObjectSerializerWriteContext)+0x17  
System_Runtime_Serialization_ni!System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(System.Runtime.Serialization.DataContract, System.Runtime.Serialization.XmlWriterDelegator, System.Object)+0x2a  
System_Runtime_Serialization_ni!System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(System.Runtime.Serialization.XmlWriterDelegator, System.Object)+0x8a  
System_Runtime_Serialization_ni!System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(System.Runtime.Serialization.XmlWriterDelegator, System.Object)+0x1f  
Share Comments
comments powered by Disqus