Showing posts with label code. Show all posts
Showing posts with label code. Show all posts

Sunday, July 31, 2011

Helper class for creating memory dumps of a Managed Process

I'm giving a talk at TechEd NZ 2011 in about a month. As part of that talk, I'll mention creating memory dumps using the MiniDumpWriteDump function, and show a helper class which P/Invokes it

Here is that helper class (Updated 19 Sept 2011 to fix some bugs).


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

public static class DbgHelp
{
    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    struct MINIDUMP_EXCEPTION_INFORMATION
    {
        public uint ThreadId;
        public IntPtr ExceptionPointers;

        [MarshalAs(UnmanagedType.Bool)]
        public bool ClientPointers;
    }

    [DllImport("Dbghelp.dll")]
    static extern bool MiniDumpWriteDump(
        IntPtr hProcess,
        uint ProcessId,
        IntPtr hFile,
        [MarshalAs(UnmanagedType.I4)] MiniDumpType DumpType,
        IntPtr ExceptionParam, // Ptr to MINIDUMP_EXCEPTION_INFORMATION
        IntPtr UserStreamParam,
        IntPtr CallbackParam);

    [DllImport("kernel32.dll")]
    static extern uint GetCurrentThreadId();

    enum MiniDumpType : int
    {
        MiniDumpNormal = 0x00000000,
        MiniDumpWithDataSegs = 0x00000001,
        MiniDumpWithFullMemory = 0x00000002, // required for .NET apps
        MiniDumpWithHandleData = 0x00000004,
        MiniDumpFilterMemory = 0x00000008,
        MiniDumpScanMemory = 0x00000010,
        MiniDumpWithUnloadedModules = 0x00000020,
        MiniDumpWithIndirectlyReferencedMemory = 0x00000040,
        MiniDumpFilterModulePaths = 0x00000080,
        MiniDumpWithProcessThreadData = 0x00000100,
        MiniDumpWithPrivateReadWriteMemory = 0x00000200,
        MiniDumpWithoutOptionalData = 0x00000400,
        MiniDumpWithFullMemoryInfo = 0x00000800,
        MiniDumpWithThreadInfo = 0x00001000,
        MiniDumpWithCodeSegs = 0x00002000,
        MiniDumpWithoutAuxiliaryState = 0x00004000,
        MiniDumpWithFullAuxiliaryState = 0x00008000,
        MiniDumpWithPrivateWriteCopyMemory = 0x00010000,
        MiniDumpIgnoreInaccessibleMemory = 0x00020000,
        MiniDumpWithTokenInformation = 0x00040000
    };

    public static void WriteExceptionDump(string filePath)
    {
        var proc = Process.GetCurrentProcess();
        int win32Error;
        if(!TryCreateDump(filePath, proc.Handle, (uint)proc.Id, GetCurrentThreadId(), Marshal.GetExceptionPointers(), out win32Error))
            throw new Exception("Couldn't create dump file! Error: 0x" + win32Error.ToString("X8"));
    }

    public static bool TryCreateDump(string dumpFilePath, IntPtr processHandle, uint processId, uint threadId, IntPtr exceptionPointers, out int win32Error)
    {
        bool success = false;
        int lastError = 0;

        // Dump on a seperate thread - IsBackground=false is important to stop the process exiting while we write the dump
        // also works around an issue of VS not being able to walk the callstack of the crashing thread
        var thread = new Thread(new ThreadStart(() => {
            // In-process dumps must ClientPointers = false
            // If ClientPointers is false, or if there are no ExceptionPointers we must pass IntPtr.Zero as ExceptionInfo
            var exceptionParam = IntPtr.Zero;
            if (processId != Process.GetCurrentProcess().Id && exceptionPointers != IntPtr.Zero)
            {
                var ei = new MINIDUMP_EXCEPTION_INFORMATION {
                    ClientPointers = true, // in-process dump. True if we're dumping external processes
                    ExceptionPointers = exceptionPointers, // may be IntPtr.zero for CLR exceptions
                    ThreadId = threadId,
                };
                exceptionParam = Marshal.AllocHGlobal(Marshal.SizeOf(ei));
                Marshal.PtrToStructure(exceptionParam, ei);
            }

            using (var outputFile = new FileStream(dumpFilePath, FileMode.Create))
            {
                success = MiniDumpWriteDump(
                    processHandle,
                    processId,
                    outputFile.SafeFileHandle.DangerousGetHandle(),
                    MiniDumpType.MiniDumpWithFullMemory,
                    exceptionParam,
                    IntPtr.Zero,
                    IntPtr.Zero);
            }

            if (!success)
                lastError = Marshal.GetLastWin32Error();

            if (exceptionParam != IntPtr.Zero)
                Marshal.FreeHGlobal(exceptionParam);
        })) { IsBackground = false, Name = "MiniDump thread" };

        thread.Start();
        thread.Join();

        win32Error = lastError;
        return success;
    }
}




Tuesday, July 29, 2008

Ruby Unit Converting Hash

I'm currently working on a project where I need to convert from things in one set of units to any other set of units ( eg centimeters to inches and so forth)

I had a bunch of small helper functions to convert from X to Y, but these kept growing every time we needed to handle something which hadn't been anticipated.

This kind of thing is also exponential, as if we have 4 'unit types' and we add a 5th one, we need to add 8 new methods to convert each other type to and from the new type

A few hours of refactoring later, I have this, which I think is kind of cool, and will enable me to delete dozens of small annoying meters_to_pts methods all over the place.

Disclaimer: This is definitely not good OO. A hash is not and never should be a unit converter. In the production code I will refactor this to build an actual Unit Converter class which stores a hash internally :-)


# Builds a unit converter object given the specified relationships
#
# converter = UnitConverter.create({
#  # to convert FROM a TO B, multiply by C
#  :pts    => {:inches => 72},
#  :inches => {:feet   => 12},
#  :cm     => {:inches => 2.54, 
#              :meters => 100},
#  :mm     => {:cm     => 10},
# })
#
# You can then do
#
# converter.convert(2, :feet, :inches) 
# => 24
#
# The interesting part is, it will follow any links which can be inferred
# and also generate inverse relationships, so you can also (with the exact same hash) do
#
# converter.convert(2, :meters, :pts) # relationship inferred from meters => cm => inches => pts
# => 5669.29133858268
#
class UnitConverter < Hash
  
  # Create a conversion hash, and populate with derivative and inverse conversions
  def self.create( hsh )
    returning new(hsh) do |h|
      # build and merge the matching inverse conversions
      h.recursive_merge! h.build_inverse_conversions
      
      # build and merge implied conversions until we've merged them all
      while (convs = h.build_implied_conversions) && convs.any?
        h.recursive_merge!( convs )
      end
    end
  end
  
  # just create a simple conversion hash, don't build any implied or inverse conversions
  def initialize( hsh )
    merge!( hsh )
  end
  
  # Helper method which does self.inject but flattens the nested hashes so it yields with |memo, from, to, rate|
  def inject_tuples(&block)
    h = Hash.new{ |h, key| h[key] = {} }
    
    self.inject(h) do |m, (from, x)|
      x.each do |to, rate|
        yield m, from, to, rate
      end
      m
    end
  end
  
  # Builds any implied conversions and returns them in a new hash
  # If no *new* conversions can be implied, will return an empty hash
  # For example
  # {:mm => {:cm => 10}, :cm => {:meters => 100}} implies {:mm => {:meters => 1000 }}
  # so that will be returned
  def build_implied_conversions
    inject_tuples do |m, from, to, rate|
      if link = self[to]
        link.each do |link_to, link_rate|
          # add the implied conversion to the 'to be added' list, unless it's already contained in +self+,
          # or it's converting the same thing (inches to inches) which makes no sense
          if (not self[from].include?(link_to)) and (from != link_to)
            m[from][link_to] = rate * link_rate 
          end
        end
      end
      m
    end
  end
  
  # build inverse conversions
  def build_inverse_conversions
    inject_tuples do |m, from, to, rate|
      m[to][from] = 1.0/rate
      m
    end
  end
  
  # do the actual conversion
  def convert( value, from, to )
    value * self[to][from]
  end
end

I'm not sure if deriving it from Hash is the right way to go, but it basically is just a big hash full of all the inferred conversions, so I'll leave it at that.


Update

Woops, this code requires 'returning' which is part of rails' ActiveSupport, and an extension to the Hash class called recursive_merge!, which I found on an internet blog comment somewhere (so it's only fitting that I share back with this unitconverter)

Code for recursive_merge


class Hash
  def recursive_merge(hsh)
    self.merge(hsh) do |key, oldval, newval|
      oldval.is_a?(Hash) ? 
        oldval.recursive_merge(newval) :
        newval
    end
  end
  
  def recursive_merge!(hsh)
    self.merge!(hsh) do |key, oldval, newval|
      oldval.is_a?(Hash) ? 
        oldval.recursive_merge!(newval) :
        newval
    end
  end
end

Code for returning

class Object
  def returning( x )
    yield x
    x
  end
end