0

Our product consumes a lot of windows resources, such as socket handles, memory, threads and so on. Usually there are 700-900 active threads, but in some cases product can rapidly create new threads and do some work, and close it. I came across with crash memory dump of our product. With ~* windbg command I can see 817 active threads, but when I run !handle command it prints me these summary:

Type            Count
None            15
Event           2603
Section         13
File            705
Directory       4
Mutant          32
WindowStation   2
Semaphore       789
Key             208
Process         1
Thread          5766
Desktop         1
IoCompletion    308
Timer           276
KeyedEvent      1
TpWorkerFactory 48

So, actually process holds 5766 threads. So, my question, When Windows actually frees handles for process? Is it possible some kind of delay, or cashing? Can someone explain this behavior? I don't think that we have handle leaks, but we have weird behavior in legacy part of system with rapidly creating and closing threads for small tasks. Also I would like to point, that we unlikely run more than 1000 threads simultaneously, I am pretty sure about this. Thanks.

Anz
  • 21
  • 3

1 Answers1

2

When you say So, actually process holds 5766 threads., what you really mean is that the process holds 5766 thread handles.

Even though a thread may no longer be running, whether that is the result of a call to ExitThread()/TerminateThread() or returning from the ThreadProc, any handles to that thread will remain valid. This makes it possible to do things like call GetExitCodeThread() on the handle of a thread that has finished its work.

Unfortunately, that means that you have to remember to call CloseHandle() instead of just letting it leak. The MSDN example on Creating Threads covers this to some extent.

Another thing that I will note is that somewhere not too far above 1000 running threads, you are likely to exhaust the amount of virtual address space available to a 32bit process since each thread by default reserves 1MB of address space for its stack.

Community
  • 1
  • 1
Sean Cline
  • 6,979
  • 1
  • 37
  • 50
  • Actually we use boost::thread::join(), to wait while thread stops. I have to check boost thread library about calling CloseHandle(). I am aware about default stack size, we override this value to 256k for our product. Thank you nevertheless. – Anz Apr 19 '13 at 15:55