4
votes

I'm looking for some random crashes in an old c++ application. Using sysinternals process explorer, I noticed the app losing handles, and extracted the exact situation, where the program is losing handles to a very short piece of code.

DWORD WINAPI MyTestThread( void*  PThread)
{
 _endthreadex(0);
 return 0;
}

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR  PParameter, int)
{
 for (int i=0;i<10000;i++)
 {
   unsigned int threadID;
   HANDLE hThread= (HANDLE)_beginthreadex( (void*)NULL, (unsigned int)32768, (unsigned int (__stdcall *)(void *))MyTestThread, (void*)NULL, (unsigned int)0, &threadID);
   WaitForSingleObject((HANDLE)hThread, 1000);
   CloseHandle((HANDLE)hThread);
 }
 return 0;
}

My problem: I can't figure out what's wrong with this code. It loses exactly 5 handles on every iteration, but it looks OK to me.
Funny thing: it seems not to lose handles on windows vista, but I'd be very surprised if this should be a bug in windows 7.

[Update] I tried using _beginthread/_endthread and CreateThread/ExitThread instead, those two are losing 5 handles, too, just like _beginthreadex.

[2nd Update] the code does run as expected. All return values are good. It is 'just' losing handles like there is no tomorrow.

[3rd Update] Big new Info The code only loses handles, if compiled with /clr! And more, if I call GC::Collect() on each iteration the handles will be reclaimed!
So, how do I find what clr-objects are being collected there?

4
What happens if you have the thread sleep for a little while? Does the call to WaitForSingleObject ever return a timeout error? You only wait one second. Any minor load on your box might cause a second to go by - jmucchiello
It is not like some of the threads lose handles: Every single thread loses exactly 5 handles, summing up 50000 lost handles in this simple loop. This is just a simplified extract from a large scale c++ app, where, too, every thread loses 5 handles. If this is a glitch, it's a huge one, not? - Sam
for the love of god why do you cast everything? half of the things you cast are already the correct type. For example: (HANDLE)hThread ...where hThread is already a HANDLE. Not a good programming practice at all. - Evan Teran
Well it is a beta, it should not be bug free. You can report it to Microsoft. - Ismael
@Evan, I did not provide this code sample as an example of good programming, but as an example to reproduce an error. - Sam

4 Answers

2
votes

Check whether some DLL which is linked to your exe is doing something strange in its DLLMain in response to DLL_THREAD_ATTACH notifications.

1
votes

Have you checked if the functions succeed? The return values and GetLastError() could give some hints what's going wrong.

1
votes

From http://msdn.microsoft.com/en-us/library/kdzttdcb.aspx

"If successful, each of these functions returns a handle to the newly created thread; however, if the newly created thread exits too quickly, _beginthread might not return a valid handle (see the discussion in the Remarks section). _beginthread returns -1L on an error, in which case errno is set to EAGAIN if there are too many threads, to EINVAL if the argument is invalid or the stack size is incorrect, or to EACCES in the case of insufficient resources (such as memory). _beginthreadex returns 0 on an error, in which case errno and _doserrno are set. "

Your thread does exit kind of quickly doesn't it.

0
votes

Have you tried testing this with Win32's CreateThread? That could possibly narrow down the problem to the CRT.