The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Archive for the '.NET bugs' Category

The Joys Of Debugging ASP.NET Memory Leaks

Posted by Davy Brion on 6th April 2009

One of my coworkers describes a very interesting memory leak he just fixed. Be sure to read his post to get the entire story.

We basically had a custom UserControl which contained (among other things) a Repeater which would render another custom UserControl. Nothing really weird there, right? The problem was that the custom UserControl that was created by the Repeater explicitly needed to be disposed. No problem, System.Web.UI.Control implements IDisposable so we could just override the Dispose method, perform our cleanup there and then proceed with the base Dispose implementation.

Now, i’m far from an ASP.NET expert but i was under the impression that all Page and UserControl instances would always have their Dispose method called if they were created by other ASP.NET controls (containing pages or controls). After all, what’s the point in implementing IDisposable in the base Control class if you’re not even going to guarantee proper usage of the pattern, right?

Well, as Kristof describes in his post, there is at least one situation where a UserControl is not disposed of, even though it was created by a Repeater. In our case, the leak was subtle. It took a stress test of 10 hours with a load that would be comparable to real world usage of one month to expose the leak. A lot of people would say “oh, let’s just recycle the application pool periodically and everything is A-OK”. But the very idea of having to recycle an application pool periodically to keep a system up and running is just a cop out to me. Good code should not require periodic restarts. Period.

I wonder how many ASP.NET WebForms applications might actually have the same (or at least similar) problem(s) like the one Kristof encountered. If everyone keeps recycling their application pools periodically, we unfortunately may never found out.

Posted in .NET bugs, ASP.NET, Memory Management | 2 Comments »

Exceptional Exception Handling Behavior

Posted by Davy Brion on 8th October 2008

We ran into a weird issue at work today. Take a look at the following code:

    public class MyException : Exception { }

 

    [TestFixture]

    public class TestFixture

    {

        [Test]

        public void Test()

        {

            var exception = GetThrownException<MyException>(() => { throw new MyException(); });

            Assert.IsNotNull(exception);

        }

 

        private T GetThrownException<T>(Action action)

            where T : Exception

        {

            try

            {

                action();

            }

            catch (T exception)

            {

                return exception;

            }

 

            return null;

        }

    }

If you simply run that test, without debugging, it works (both with Testdriven.NET and Resharper). If you run it with a debugger, it fails with the following message:

ExceptionWeirdness.MyException: Exception of type ‘ExceptionWeirdness.MyException’ was thrown.

Pretty weird huh?

Let’s change the code of the GetThrownException method to this:

        private T GetThrownException<T>(Action action)

            where T : Exception

        {

            try

            {

                action();

            }

            catch (T exception)

            {

                return exception;

            }

            catch (Exception e)

            {

                return (T)e;

            }

 

            return null;

        }

Now the test works all the time, even with the debugger attached.

Weird huh? At first i wondered if it was somehow NUnit related… but then i tried running this program:

    public class MyException : Exception { }

 

    class Program

    {

        static void Main(string[] args)

        {

            var exception = GetThrownException<MyException>(() => { throw new MyException(); });

        }

 

        private static T GetThrownException<T>(Action action)

            where T : Exception

        {

            try

            {

                action();

            }

            catch (T exception)

            {

                return exception;

            }

 

            return null;

        }

    }

Run it without the debugger, and it works. Run it with the debugger and it fails.

This is using .NET 3.5 SP1.

I don’t understand why it behaves like this… it should work all the time right? I am overdue for my weekly brain-fart so i might be missing something really stupid though.

Either way, the first person to explain this behavior gets awarded with the “Davy Brion’s Hero Of The Week” title :)

Oh, and this was in a clean solution… so there’s no duplicate MyException types or anything like that.

Posted in .NET bugs | 20 Comments »

XDocument’s WriteTo method gotcha

Posted by Davy Brion on 25th April 2008

Suppose you have an xml document in memory using an XDocument instance. Then you need to write the contents of the xml document to an XmlWriter… no worries, the XDocument class provides the WriteTo method which takes an XmlWriter as a parameter. The contents of the xml document are then nicely written to the XmlWriter.

Unless… you’re using an XmlWriter which was created with an XmlWriterSettings instance with OutputMethod set to XmlOutputMethod.Text and your xml document is larger than 6144 bytes! The writer will only write the first 6144 bytes and after that, it just stops. No exception, no nothing. The method returns as if everything was OK. But the underlying stream your XmlWriter wrote to contains faulty data. A very nice way to spend a friday afternoon ;)

In case you’re wondering why: The XmlWriter’s static Create method creates an instance of XmlUtf8RawTextWriter when OutputMethod is set to XmlOutputMethod.Text. This specific Writer has an internal buffer which is initialized in its constructor to be 6144 bytes long. Apparantly, it doesn’t think it’s worth throwing an exception if you try to write too much data…

Posted in .NET bugs | 1 Comment »