Skip to content

Instantly share code, notes, and snippets.

View Criteo-dotnet-blog's full-sized avatar

Criteo-dotnet-blog

View GitHub Profile
public class TimerInfo
{
    public ulong TimerQueueTimerAddress { get; set; }
    public uint DueTime { get; set; }
    public uint Period { get; set; }
    public bool Cancelled { get; set; }
    public ulong StateAddress { get; set; }
    public string StateTypeName { get; set; }
    public ulong ThisAddress { get; set; }
    public string MethodName { get; set; }
public IEnumerable<TimerInfo> EnumerateTimers(ClrRuntime runtime)
{
   ClrHeap heap = runtime.GetHeap();
   if (!heap.CanWalkHeap)
      yield break;
private ClrModule GetMscorlib(ClrRuntime runtime)
{
    foreach (ClrModule module in runtime.Modules)
        if (module.AssemblyName.Contains("mscorlib.dll"))
            return module;
    // Uh oh, this shouldn't have happened.  Let's look more carefully (slowly).
    foreach (ClrModule module in runtime.Modules)
        if (module.AssemblyName.ToLower().Contains("mscorlib"))
            return module;
var timerQueueType = GetMscorlib(runtime).GetTypeByName("System.Threading.TimerQueue");
ClrStaticField staticField = timerQueueType.GetStaticFieldByName("s_queue");
foreach (ClrAppDomain domain in runtime.AppDomains)
{
    ulong? timerQueue = (ulong?)staticField.GetValue(domain);
    if (!timerQueue.HasValue || timerQueue.Value == 0)
        continue;
private object GetFieldValue(ClrHeap heap, ulong address, string fieldName)
{
    var type = heap.GetObjectType(address);
    ClrInstanceField field = type.GetFieldByName(fieldName);
    if (field == null)
        return null;
    return field.GetValue(address);
}
var val = GetFieldValue(heap, currentTimerQueueTimerRef, "m_dueTime");
ti.DueTime = (uint)val;
val = GetFieldValue(heap, currentTimerQueueTimerRef, "m_period");
ti.Period = (uint)val;
val = GetFieldValue(heap, currentTimerQueueTimerRef, "m_canceled");
ti.Cancelled = (bool)val;
val = GetFieldValue(heap, currentTimerQueueTimerRef, "m_state");
ti.StateTypeName = "";
if (val == null)
{
ti.StateAddress = 0;
}
else
{
ti.StateAddress = (ulong)val;
var stateType = heap.GetObjectType(ti.StateAddress);
// decypher the callback details
val = GetFieldValue(heap, currentTimerQueueTimerRef, "m_timerCallback");
if (val != null)
{
ulong elementAddress = (ulong)val;
if (elementAddress == 0)
continue;
var elementType = _heap.GetObjectType(elementAddress);
if (elementType != null)