views:

160

answers:

2

The following code works fine until I upgrade to .NET 4 (x64)

namespace CrashME
{
    class Program
    {
        private static volatile bool testCrash = false;
        private static void Crash()
        {
            try
            {
            }
            finally
            {
                HttpRuntime.Cache.Insert("xxx", testCrash);
            }

        }

        static void Main(string[] args)
        {
            Crash();
            // Works on .NET 3.5 , crash on .NET 4
        }
    }
}

Did I just uncover a runtime bug, or is there some issue with my usage?

+3  A: 

This would appear to be a bug in the CLR - you should report it to Microsoft.

Note that the StackOverflowException occurs as the CLR attempts to execute the Crash, not during the execution of the Crash method - the program in fact never enters the method. This would appear to indicate that this is some low-level failure in the CLR. (Also note that the thrown exception also has no stack trace).

This exception is incredibly specific to this situation - changing any one of a number of things fixes this, for example the following code works fine:

private static void Crash()
{
    bool testCrash2 = testCrash;
    try { }
    finally
    {
        HttpRuntime.Cache.Insert("xxx", testCrash2);
    }
}

I would recommend that you report this to Microsoft, but attempt to work around the issue by tweaking your code in the meantime.

Kragen
Ok, the CLR team have been notified so we should see a fix for this at some point
Sam Saffron
+2  A: 

I can reproduce it on an x86 machine. The following code also fails:

        try
        {
        }
        finally
        {
            var foo = new List<object>();
            foo.Add(testCrash);
        }

However, the following code succeeds:

        try
        {
        }
        finally
        {
            var foo = new List<bool>();
            foo.Add(testCrash);
        }

I thought it might have something to do with the boxing of volatile fields within the finally block, but then I tried the following (which also fails):

        try
        {
        }
        finally
        {
            bool[] foo = new bool[1];
            foo[0] = testCrash;
        }

Very interesting problem...

Jim Killingsworth