Surviving the Night

El blog de Pablo Doval sobre .NET, SQL, WinDbg...

Love Bites: Generación Programática de Volcados de Memoria

Llevo mucho tiempo deseando escribir esta entrada, pero por una razón u otra nunca conseguí hacer un hueco para prepararla como es debido. Estos días he vuelto a abrir el Live Writer y me he propuesto no dejar pasar la ocasión. Además, estos últimos meses parece que solo vivo de SQL y de BI, así que estará bien por un rato volver a recordar los viejos tiempos con WinDbg ;)

Así que a ver si consigo que este pequeño artículo le haga justicia a lo interesante que es la técnica que os quiero enseñar hoy. ¡Al turrón!

Depuración Post-Mortem

No puedo evitarlo, ¡me encanta este término! Creo que cada vez que lo empleo se me concede automáticamente un +10 en geek skills :) Tonterías aparte, creo que la depuración post-mortem nos proporciona uno de los escenarios más interesantes desde el punto de vista de soportabilidad de nuestras aplicaciones, tanto desde un enfoque técnico como económico.

Ya he hablado de este tema aquí en varias ocasiones, pero como Rodri no me cobra por palabras en el blog (aún!), voy a volver refrescar el concepto de la mejor manera que se me ocurre: con un escenario de la vida real™.

Supongamos que tenemos una aplicación desplegada en un cliente que se encuentra en la Base Amundsen-Scott. Imaginemos ahora que la aplicación revienta en el peor momento y requiere un fix urgente. Si, ya lo se, vuestras aplicaciones no revientan jamás y están testadas para todos los entornos conocidos y por conocer, pero haced el ejercicio de imaginación conmigo ;) Vamos a seguir fantaseando: el cliente os notifica el problema, pero nosotros no somos capaces de reproducirlo en nuestro entorno de ninguna de las maneras. Perdemos un tiempo precioso para el cliente intentando obtener una repro del problema y finalmente no nos queda otra que coger un avión, un barco y un trineo tirado por una docena de Alaskan Malamute(1) y llegar, posiblemente junto a una copia de nuestro código cuente o símbolos de depuración, al lugar donde se encuentra el cliente. Y ya conocéis las reglas de Murphy: el día que llegamos, ¡¡seguro que el problema no se reproduce!!

Y si en lugar de ir nosotros al lugar donde se produjo el problema, fuéramos capaces de hacer llegar el equipo con el fallo a nuestras instalaciones, justo en el mismo instante que se ha producido, y con un depurador ya adjuntado. ¿No sería genial? Pues en realidad podemos conseguir algo aún mejor: obtener esa información sin tener que enviar el equipo físicamente :) Se trata de capturar un volcado de memoria (memory dump, o dump para los amigos), consiste en una copia (total o parcial) de los contenidos del espacio de memoria virtual del proceso.

Este fichero con el volcado de memoria podemos abrirlo con un depurador (como mi queridísimo WinDbg) y obtenemos una imagen del proceso en el momento exacto que reventó: podremos ver la pila de llamadas de todos los hilos, examinar las excepciones lanzadas, valores de las variables, etc.

Pensemos ahora en otro tipo de escenario: software que pueda ejecutarse en muchos equipos, y muy diferentes cada uno de ellos, como por ejemplo los videojuegos. En esta industria se emplean mucho la generación automática de memoria, porque el numero de usuarios y la gran dependencia sobre el hardware especifico hace imposible testar todos los entornos hardware y software en los que el producto se va a ejecutar.

OPINION PERSONAL: Esto nos podría llevar al debate de si es ético que un producto salga al mercado con fallos o incompatibilidades, y tengan que ser los propios usuarios de pago los que hagan de ‘conejillos de indias’… pero voy a tratar de evitar entrar en este espinoso tema… al menos por hoy ;)

Otros escenarios que nos pueden interesar de la generación de volcados de memoria automatizados pueden ser los siguientes:

  • Clasificador de Incidencias en la Aplicación:

¿Os suena de algo la ventanita de Windows que nos pregunta si queremos enviar un informe de errores a Microsoft cuando una aplicación revienta? Pues cuando envías el informe, en realidad se captura el volcado de memoria y un hash de este y se almacena en unos servidores de bases de datos de Microsoft. Un proceso clasifica todos los incidentes que tienen call stack similar, clasificándolo como potencialmente el mismo problema, e incrementando un contador.

De este modo, la gente de los equipos de desarrollo de hotfixes saben donde tienen que centrar sus esfuerzos, atacando primero la resolución de los problemas que impactan a un mayor número de usuarios.

Por tanto, mi recomendación es que siempre enviéis los informes de errores, ya que eso hará que vuestros problemas puedan ser atendidos más rápidamente. Y no, no os va a delatar si tenéis un Windows poco legal, ni le va a decir a Microsoft que habéis estado mirando páginas de dudoso valor moral :P

  • Capturas Periódicas para Evaluar Uso de Aplicación:

El volcado de memoria no tiene porque realizarse como respuesta directa a una situación de error en la aplicación. Podemos realizar capturas periódicas para evaluar el uso de la aplicación.

<IdaDePinza Modo=”Plan de Dominación Mundial”>

Imaginaros lo divertido que sería generar mini dumps periódicos cada 10 segundos de todos los usuarios de nuestra aplicación y volcarlos a un entorno Hadoop y hacer MapReduce para conocer patrones de uso…. Muahahahaha!

</IdaDePinza >

¿Cómo generar los volcados de memoria?

En realidad se trata de algo mucho más sencillo de lo que parece, ya que la funcionalidad para generar los Mini Dumps nos la proporciona directamente DbgHelp.dll, la librería de depuración del sistema. Podemos acceder a la última versión a través de las Debugging Tools for Windows, y distribuirla junto con nuestra aplicación. Esta DLL nos proporciona una gran cantidad de funcionalidad interesante para realizar operaciones con los símbolos, búsquedas y relaciones con el código fuente, etc… pero nos vamos a centrar en este caso en una única función expuesta: MiniDumpWriteDump.

Esta función recibe ciertos parámetros (handle al proceso del que queremos obtener el volcado (en este caso será el propio proceso), el PID,  otro manejador al fichero de salida donde vamos a dejar el dump, etc.) y nos genera el dump por nosotros; como veis, todo muy sencillito!

Armados con esta información, solo nos queda importar la función en nuestro código y empezar a usarla. Aquí os dejo un código de referencía en C# para importar e invocar a la función MiniDumpWriteDump de DbgHelp.dll:

using System; 
using System.Runtime.InteropServices; 
using System.IO; 
using System.Diagnostics;

namespace PlainConcepts.DumpGenerator 
{ 
    public enum MINIDUMP_TYPE 
    { 
        MiniDumpNormal = 0x00000000, 
        MiniDumpwithDataSegs = 0x00000001, 
        MiniDumpWithFullMenory = 0x00000002, 
        MiniDumpWithHandleData = 0x00000004, 
        MiniDumpFilterMemory = 0x00000008, 
        MiniDumpScanMemory = 0x00000010, 
        MiniDumpwithUnloadedModules = 0x00000020, 
        MiniDumpwithlndirectlyReferencedMemory = 0x00000040, 
        MiniDumpFilterModulePaths = 0x00000080, 
        MiniDumpwithProcessThreadData = 0x00000100, 
        MiniDumpWithPrivateReadWriteMemory = 0x00000200, 
        MiniDumpWithoutOptionaloata = 0x00000400, 
        MiniDumpWithFullMemoryInfo = 0x00000800, 
        MiniDumpwithThreadInfo = 0x00001000, 
        MiniDumpwithCodesegs = 0x00002000 
    }

    public class DumpGenerator 
    { 
        [DllImport("dbghelp.dll")] 
        static extern bool MiniDumpWriteDump( 
        IntPtr hProcess, 
        Int32 processld, 
        IntPtr hFile, 
        MINIDUMP_TYPE dumpType, 
        IntPtr exceptionParam, 
        IntPtr userStreamParam, 
        IntPtr callbackParam);

        public static void MiniDumpToFile(string file) 
        { 
            FileStream dumpFile = null; 
            if (File.Exists(file)) 
                dumpFile = File.Open(file, FileMode.Append); 
            else 
                dumpFile = File.Create(file);

            Process currentProcess = Process.GetCurrentProcess(); 
            MiniDumpWriteDump(currentProcess.Handle, 
                              currentProcess.Id, 
                              dumpFile.SafeFileHandle.DangerousGetHandle(), 
                              MINIDUMP_TYPE.MiniDumpNormal, 
                              IntPtr.Zero, 
                              IntPtr.Zero, 
                              IntPtr.Zero); 
            dumpFile.Close(); 
        } 
    } 
} 

No es el código mas robusto, y presenta ciertos problemas al estar ejecutándose en un hilo del mismo proceso, pero para empezar a trastear creo que será mas que suficiente.

Y ahora… ¿que hacemos con ellos?

Ahora podemos analizarlos usando herramientas como WinDbg. El análisis de los mismos esta fuera del ámbito de esta entrada, pero os recomiendo que veáis las entradas introductorias a WinDbg en este blog y, sobre todo, los materiales de depuración de Tess Ferrandez, Ingeniera de Escalación de Microsoft y una autentica crack a la hora de explicar escenarios de depuración .NET con WinDbg.

Y con esto, creo que por fin he saldado mi pequeña deuda personal con este artículo. Espero que os haya sido de utilidad, o al menos os haya dado alguna idea de para vuestros propios planes personales de dominación mundial ;)

(1): Si, lo sé, la Base Amundsen-Scott tiene su propia pista (NZSP); podríamos llegar sin barco y sin trineo tirado por perros, pero seguro que me permitís esa pequeña licencia artística para darle un punto de romanticismo a nuestro épico viaje ;)

Rock Tip:

No pude evitar hacer el chiste malo, el juego de palabras que me sirve como excusa para traer en una nueva ocasión a una de las mejoras bandas del Hard Rock/AOR de las islas británicas a mi blog: una vez más, con todos ustedes, directamente desde Sheffield….Def Leppard!!!

En esta ocasión, el tema ‘Love Bites’ será el que nos acompañara. Aparecido en su espectacular LP ‘Hysteria’ en 1987, sería uno de los singles más exitosos del mismo, ¡lo que no es decir poco! Si habéis pinchado en el enlace a la canción en YouTube, habréis comprobado que no se trata de una versión cualquiera; es el directo de Sheffield de 1993, una interpretación que me pone los pelos como escarpias. Hacia solo un par de años que Steve Clark había fallecido, pero Vivian Campbell ya estaba perfectamente integrado en la banda, Rick Allen ya volvía a tocar con sets acústicos de batería y la banda estaba en el que posiblemente fuera uno de los mejores estados de forma de toda su carrera. ¡Atención al final que se curran para este increíble temazo!

Evidentemente, he decidido poner esta canción como Rock Tip™ del post porque gracias a la técnica que os explico más arriba vamos a ser capaces de extraer automáticamente esos ‘bits del amor’, ese volcado de memoria sobre el cual podremos hacer nuestro análisis post-mortem. Mmm… ¿rebuscado? Puede, pero… ¡intentad vosotros sacar un rock tip para cada artículo, a ver que os sale! XDD

Como anécdota personal os diré que a esta canción le tengo un cariño especial porque se trata de la primera canción que escuche en MP3 hace muchos, muchos años… cuando tenias que decidir si querías escuchar un MP3 o hacer otra cosa con el ordenador, porque era imposible hacer alguna otra tarea simultáneamente a la reproducción… ¡que tiempos!

Keep Rockin’!

Posted: 30/5/2012 20:49 por Pablo Alvarez | con 2 comment(s)
Archivado en:
Comparte este post:

Comentarios

Kiquenet ha opinado:

Pablo, se agradecen estos temas de Depuración Post-Mortem :-)

Otras buenas referencias:

voneinem-windbg.blogspot.com.es/.../creating-and-analyzing-minidumps-in-net.html

stackoverflow.com/.../generating-net-crash-dumps-automatically

Saludos.

# June 1, 2012 1:33 PM

Pablo Alvarez ha opinado:

Gracias Kiquenet! Tanto por el comentario como por los aportes :)

Un abrazo!

# June 1, 2012 1:52 PM