Dead Threads

If you ever debug memory dump using windbg+sos, you might see that there are dead threads when using !threads and wonder what they mean.  Let's take a look a the below example.

0:002> !threads
ThreadCount: 242
UnstartedThread: 0
BackgroundThread: 89
PendingThread: 0
DeadThread: 151
Hosted Runtime: no
                                              PreEmptive                                                Lock
       ID OSID        ThreadOBJ     State   GC     GC Alloc Context                  Domain           Count APT Exception
   7    1  e14 0000000003606740      8220 Enabled  0000000000000000:0000000000000000 00000000035ff100     0 Ukn
  24    2  d1c 000000000360de10      b220 Enabled  0000000000000000:0000000000000000 00000000035ff100     0 MTA (Finalizer)
  25    3  e54 000000000362a900    80a220 Enabled  0000000000000000:0000000000000000 00000000035ff100     0 MTA (Threadpool Completion Port)
  26    4  c38 000000000362eed0      1220 Enabled  0000000000000000:0000000000000000 00000000035ff100     0 Ukn
  27    7  eb8 00000000036f22d0   380b220 Enabled  0000000000000000:0000000000000000 000000000362f4a0     0 MTA (Threadpool Worker)
  28    8  c58 0000000003742a20   380b220 Enabled  0000000000000000:0000000000000000 000000000362f4a0     0 MTA (Threadpool Worker)
  29    9  c84 000000000373d010   380b220 Enabled  0000000000000000:0000000000000000 000000000362f4a0     0 MTA (Threadpool Worker)
   2    a  aa8 000000000378b8d0       220 Enabled  000000004514f608:0000000045151228 00000000035ff100     0 Ukn
  30    c  a3c 000000000378c470   200b020 Enabled  0000000000000000:0000000000000000 000000000362f4a0     0 MTA Microsoft.Cis.Fabric.Controller.Client.V1_0.StsNotAvailableException (000000002501d528)
  31    d  dc4 000000000378ca40   200b020 Enabled  0000000000000000:0000000000000000 000000000362f4a0     0 MTA System.Threading.WaitHandleCannotBeOpenedException (0000000003cfd1a0)
  21    e  c88 000000000378d010   a80a220 Enabled  0000000000000000:0000000000000000 000000000362f4a0     0 MTA (Threadpool Completion Port)
  32    b  d70 000000000378bea0       220 Enabled  0000000000000000:0000000000000000 00000000035ff100     0 Ukn
  34   1c  8c0 0000000003791000   380b220 Enabled  0000000000000000:0000000000000000 000000000362f4a0     0 MTA (Threadpool Worker)
XXXX 13 0 0000000003792170 1801820 Enabled 0000000000000000:0000000000000000 00000000035ff100 0 MTA (Threadpool Worker)
XXXX 19 0 000000001f371b10 1801820 Enabled 0000000000000000:0000000000000000 00000000035ff100 0 MTA (Threadpool Worker)
XXXX 10 0 000000001f3709a0 1801820 Enabled 0000000000000000:0000000000000000 00000000035ff100 0 MTA (Threadpool Worker)

You will see some threads which don't have a debugger session ID and also have OSID as 0. Those are dead threads.   They are actually managed code threads but the corresponding OS threads don't exist anymore (true for most cases) or haven't been created yet.  The dead threads are holding a lot of resources. If there are many of them and they don't get recycled by GC for a while, it may indicate a memory leak somewhere. For the above example, there are 151 dead threads which indicates a good candidate for memory leak.

 I will talk about a memory leak related to dead threads in next post which is very interesting because it turned out to be a .net bug.