Thursday 26 December 2013

The process was terminated due to an internal error in the .NET Runtime


If your .NET process crashes unexpectedly with the following message in the Event Log: "The process was terminated due to an internal error in the .NET Runtime...", there are a few things we can do to investigate it. Unfortunately, the exception already occurred, the process crashed and there is nothing interesting in the logs. First of all we'd like to find out what happens that causes to this crash and where in the code it happens. In order to do this we can start by downloading and installing Debug Diagnostic tool. Then configuring it in the following matter:

Select Crash, because that's what we're investigating:


Select a specific process, because we know what process crashes:


Select the process you want to investigate:


Select "Full Userdump":

With the DebugDiag running in the background, reproduce the scenario that causes the initial process termination. When the process crashes, we'll find in DebugDiag log folder with a few files. The log folder is
C:\Program Files\DebugDiag\Logs
The interesting file is the one with .DMP extension. Double click it and it will be opened in DeBug Diagnostic Analysis. It will convert the DMP file to HTML report and will open it in IE. Yes, yes, IE, even if your favorite browser is Chrome. Ok, ok, just give me the call stack

We are looking for any errors, crashes in that HTML log. In my case I found "access violation" exception and call stack of the exception. Surprisingly, the call stack is pretty obvious code. It accesses a property which is null, so I would expect a NullReferenceException. But it was access violation. What is more interesting, is that that piece of code is surrounded by try/catch block.

Starting from .NET 4.0, access violation exceptions and similar are not thrown in the regular way. They just terminate the process and are not caught in try block. But there are two still to catch them:
  • 1. Using attribute HandleProcessCorruptedStateExceptions on the suspicious method
  • 2. Using <legacyCorruptedStateExceptionsPolicy enabled="true" />
Below code demonstrates how to apply HandleProcessCorruptedStateExceptions attribute on suspicious method. It enables catching the access violation exception.
 

    internal class Program
    {
        private static void Main(string[] args)
        {
            var crashingThread = new Thread(CrashingThread);
            crashingThread.Start();

            Console.ReadKey();
        }

        [HandleProcessCorruptedStateExceptions]
        private static void CrashingThread()
        {
            try
            {
                CrashMe();
            }
            catch (Exception exception)
            {
                Console.WriteLine("I caught access violation");
                Console.WriteLine(exception.ToString());
            }
        }

        private static unsafe void CrashMe()
        {
            unsafe
            {
                int read = *((int*) long.MaxValue - 8);
            }
        }
    }



A few last notes about that attribute:
It can be applied on any level on the call stack of the suspicious code. Even on the Main method. However it won't work if you apply the attribute on the main method, but the exception occurs in another thread. It should be applied on the method that is on the crashing thread!

Please note, that it is not recommended to leave that attribute in production code. It should be used only for debugging purposes.

Enjoy your debugging!

No comments: