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!

Wednesday 11 December 2013

BizArk.Core 2.0.9 was pushed to NuGet

Bizark.Core 2.0.9 was pushed to NuGet

Release notes:
9151 Empty argument prefix does not work and does not

Example:
 
[CmdLineOptions(ArgumentPrefix = "")]
internal class MyCmdLineObject: CmdLineObject
{
     [CmdLineArg]
     public string Name { get; set; }
}
Can be used like this from command-line
MyConsoleApplication.exe Name Boris

In conjunction with ArgumentDelimiter:
 
[CmdLineOptions(ArgumentPrefix = "", ArgumentDelimiter='=')]
internal class MyCmdLineObject : CmdLineObject
{
     [CmdLineArg]
     public string Name { get; set; }
}
From command line
MyConsoleApplication.exe Name=Boris

Also supports string surrounded by double quotes:
 
[CmdLineOptions(ArgumentPrefix = "", ArgumentDelimiter='=')]
internal class MyCmdLineObject : CmdLineObject
{
     [CmdLineArg]
     public string Path { get; set; }
}
MyConsoleApplication.exe Path="C:\Program Files (x86)\Microsoft.NET\"
The value of Path will be @"C:\Program Files (x86)\Microsoft.NET\" without the leading and ending double quotes

Get from nuget:

PM> Install-Package BizArk.Core

Wednesday 4 December 2013

Goodbye Autofac

Autofac is one of my favorite IoC containers, due to its fluent, easy-to-learn syntax and great performance. However recently it let me down in some occasions and I had to get rid of it in the main project, I am working on. But let me explain it from the beginning.

Since Autofac 3.0, it is compiled against Portable .NET Framework. It is a subset of the usual .NET Framework, which runs on various devices and platforms. Such as Silverlight, mobile etc. The portable framework version number is 2.0.5.0. So far, so good. It worked well in my project with .NET Framework 4.5. But...

1. When we tried to obfuscate Autofac.dll using Dotfuscator version 4.8, it complained that mscorlib.dll version 2.0.5.0 cannot be found. Although it exists in the corresponding directory under C:\Windows\Microsoft.NET\Framework . Travis Illig suggested me to upgrade the Dotfuscator to latest version, which would definitely resolve the problem.

From Dotfuscator v 4.9 release notes:
  • Using String Encryption on Portable Class Libraries will no longer cause Windows Store apps to fail certification.
http://www.preemptive.com/support/dotfuscator-support/dotfuscator-pro-change-log/464

Unfortunately, upgrading Dotfuscator means purchasing a new license, which is pretty expensive. We managed to overcome this problem by putting mscorlib.dll v2.0.5.0 in one of the internal directories. Dotfuscator scans directories and managed to find it successfully.

2. The second problem appeared when we started testing the product on clean machines. We get the following exception, despite the fact that Portable Framework exists on the machine:

Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. 

It happens as a result of Microsoft Known Bug KB2468871. It was fixed by the Redmond folks, but the relevant update is not installed on the machine.

So it means, that in order to use Autofac we have to required from our customers to install Windows Updates. Sometimes it might cause issues with corporate customers, that have strict policy regarding machine updates. It was decided that we'll stop using Autofac in this major project and will switch to something less "sensitive".

Nevertheless, we still use Autofac in many other internal projects. So it is not a real "Goodbye"