Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OutOfMemoryError calling XmlSerializer.Deserialize() - not related to XML size!

This is a really crazy bug. The following is throwing an OutOfMemoryException, for XML snippits that are very short and simple (e.g., <ABC def='123'/>):

public static T DeserializeXmlNode<T>(XmlNode node)
{
    try
    {
        return (T)new XmlSerializer(typeof(T))
            .Deserialize(new XmlNodeReader(node));
    }
    catch (Exception ex)
    {
        throw; // just for catching a breakpoint.
    }
}

I read in this MSDN article that if I were using XmlSerializer with additional parameters in the constructor, I'd end up generating un-cached serializer assemblies every time it got called, causing an Assembly Leak. But I'm not using additional parameters in the constructor. It also happens on the first time it is called in a freshly started AppDomain, so that doesn't make sense either.

What gives?

like image 216
Mike Atlas Avatar asked May 12 '10 22:05

Mike Atlas


1 Answers

Well, the final answer to my question isn't going to help everyone that encounters this, but some of my coworkers also encountered this months later on a different system with a different product. The laughed when they found my post here on SO months later and wondered if I actually had solved it or not, since no solution was accepted here.

The final solution has nothing to do with problems Deserializing. Instead, it involved completely uninstalling and installing a brand new copy of Oracle ODP.NET database client, the provider many if not all of our applications use.

Based on anecdotal evidence, it seems this problem arises on improperly patched versions of ODP.NET assemblies, of which subsequently got propagated to other systems via virtual machine clones.

When ODP.NET was completely removed, and a new compatible version was retrieved from the Oracle website and installed, the problem disappeared completely.

The hypothesis is that a usable (but corrupt) ODP.NET driver has unsafe code and was repeatably overwriting the .NET protected memory area near the Deserialize method after first use. If Deserialize was called before any ODP.NET invocations, it would work just fine. However, all subsequent calls to Deserialize after using any ODP.NET calls would fail miserably.

The final solution to this that has now been resolved twice in two distinct products is to get a good/fresh/clean/new copy of ODP.NET installed.

Not pretty... but that's what solved it.

like image 191
Mike Atlas Avatar answered Nov 22 '22 23:11

Mike Atlas