openGenericCERCall MDA

The openGenericCERCall managed debugging assistant is activated to warn that a constrained execution region (CER) graph with generic type variables at the root method is being processed at JIT-compilation or native image generation time and at least one of the generic type variables is an object reference type.

Symptoms

CER code does not run when a thread is aborted or when an application domain is unloaded.

Cause

At JIT-compilation time, an instantiation containing an object reference type is only representative because the resultant code is shared, and each of the object reference type variables might be any object reference type. This can prevent the preparation of some run-time resources ahead of time.

In particular, methods with generic type variables can lazily allocate resources in the background. These are referred to as generic dictionary entries. For instance, for the statement List<T> list = new List<T>(); where T is a generic type variable the runtime must look up and possibly create the exact instantiation at run time, for example, List<Object>, List<String>, and so forth. This can fail for a variety of reasons beyond the developer's control, such as running out of memory.

This MDA should only be activated at JIT-compilation time, not when there is an exact instantiation.

When this MDA is activated, the likely symptoms are that CERs are not functional for the bad instantiations. In fact, the runtime has not attempted to implement a CER under the circumstances that caused the MDA to be activated. So if the developer uses a shared instantiation of the CER, then JIT-compilation errors, generics type loading errors, or thread aborts within the region of the intended CER are not caught.

Resolution

Do not use generic type variables that are of object reference type for methods that may contain a CER.

Effect on the Runtime

This MDA has no effect on the CLR.

Output

The following is a sample of output from this MDA:

Method 'GenericMethodWithCer', which contains at least one constrained execution region, cannot be prepared automatically since it has one or more unbound generic type parameters.
The caller must ensure this method is prepared explicitly at run time prior to execution.
method name="GenericMethodWithCer"
declaringType name="OpenGenericCERCall"

Configuration

<mdaConfig>
  <assistants>
    <openGenericCERCall/>
  </assistants>
</mdaConfig>

Example

The CER code is not executed.

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

class Program
{
    static void Main(string[] args)
    {
        CallGenericMethods();
    }
    static void CallGenericMethods()
    {
        // This call is correct. The instantiation of the method
        // contains only nonreference types.
        MyClass.GenericMethodWithCer<int>();

        // This call is incorrect. A shared version of the method that
        // cannot be completely analyzed will be JIT-compiled. The
        // MDA will be activated at JIT-compile time, not at run time.
        MyClass.GenericMethodWithCer<String>();
    }
}

class MyClass
{
    public static void GenericMethodWithCer<T>()
    {
        RuntimeHelpers.PrepareConstrainedRegions();
        try
        {

        }
        finally
        {
            // This is the start of the CER.
            Console.WriteLine("In finally block.");
        }
    }
}

See also