Marshall-By-Bleed explained

El otro día, mi compañero Pablo Doval puso un excelente post sobre una detección de bloqueos, más bien de interbloqueos, dentro de una aplicación en producción. De entre las muchas buenas prácticas y malas opciones a la hora de hacer sync locks dentro de las aplicaciones que comentó hubo una que por desconocida creo que merece la pena anotarla con este otro post. Pablo hizo referencia hacia un tema poco documentado en el Framework de .NET que es Marshall-By-Bleed según el cual es posible que dos dominios de aplicación distintos tengan un referencia al mismo objeto en memoria, si ya sé lo que todos hemos oído acerca del aislamiento por AppDomains, pero aún así es cierto con unas determinadas restricciones, la primera, y más restrictiva de todas, es que los tipos que disfrutan de Marshall-By-Bleed son solamente los tipos definidos en un dominio neutral como mscorlib.dll como por ejemplo Type y todos los tipos de reflexión al estilo XXXInfo. Según esto, a mayores de la mala práctica en cuanto a orientación a objetos de hacer un lock sobre typeof, podríamos tener interbloqueos realmente difíciles de detectar, si no está depurando Pablo Doval claro J ….. Los que me conocéis sabéis que siempre tiro al código para intentar explicar las cosas y esta vez no iba a ser menos por lo que aquí tenéis un pequeño tip explicativo J

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

 

 

namespace MarshallByBleed

{

class Program

{

static void Main(string[] args)

{

AutoResetEvent waitHandle = new AutoResetEvent(false);

 

lock (typeof(Program)) //cambiar a typeof(Object) para Marshall-By-Bleed

{

        AppDomain otherDomain = AppDomain.CreateDomain(“DOMAIN_B”);

        //DoCallback permite ejecutar código en

        // el ambiente de otro AppDomain

        otherDomain.DoCallBack(() =>

        ThreadPool.QueueUserWorkItem(state =>

        {

            lock (typeof(Program))//cambiar a typeof(Object) para Marshall-By-Bleed

            {

                Console.WriteLine(“No hay Marshall-By-Bleed”);

            }

        }, null)

    );

     waitHandle.WaitOne();

    }

    Console.ReadLine();

}

}

}

 

Os propongo que utilicéis el atributo LoaderOptimization para simular la carga de un dominio neutral y comprobéis como typeof(Program) también podría participar como Marshall-By-Bleed…

Saludos

Unai

7 comentarios en “Marshall-By-Bleed explained”

  1. Octavio, Pablo:Gracias por los comentarios

    JuanK: Truco? Más que un truco es un NO TRUCO, o sea lo que no se debería hacer, te recomiendo la lectura del post de Pablo Doval dónde indica los problemas que puedes llegar a tener..

    Saludos
    Unai

  2. Echando un vistazo al código del propio Framework de .NET he visto que para los bloqueos suelen hacer algo de este tipo:

    // declaración de un objeto utilizado para bloqueos entre todas las instancias de la clase actual…
    private static object syncObject = new object();

    lock(syncObject)
    {

    }

  3. ManualResetEvent, AutoResetEvent y Mutuex forman parte de los cinco ‘kernel objects’ soportados en .NET. Todos heredando de WaitHandle por lo tanto todos disponen de Set y WaitOne como métodos.
    La diferencia entre Mutex y Auto o ManuelResetEvent son de propósito, por un lado Mutex ( Mutually-Exclusive ) http://en.wikipedia.org/wiki/Mutual_exclusion tiene como propósito el manejo de secciones críticas con objetos a nivel de Kernel, pesados entre transiciones.
    Auto y Manual son objetos dedicados a la coordinacion entre hilos y aunque son similares sus diferencias son bastantes sutiles….

    Saludos
    Unai

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *