why does debugger stop on (WaitForSingleObject == WAIT_FAILED)?

Started by
14 comments, last by CPPNick 13 years, 9 months ago
Why does the debugger stop execution and give an error when WaitForSingleObject() is called on a closed HANDLE more than once? when I run my program outside of the VS2010 IDE, WaitForSingleObject(invalid handle) just returns WAIT_FAILED like its supposed to, no matter how many times I call it on the invalid handle. Is there anything actually wrong with calling it on an invalid handle?
Advertisement
You're not supposed to call WaitForSingleObject on closed/invalid handles. The documentation also states that if a handle you're waiting on is closed, the function's behavior is undefined. The debugger is trying to tell you something is wrong, even if you don't get any errors otherwise. Why are you attempting to call that function on closed handles anyway?
I am writing a file transfer program that uses a separate thread to send the file

here is some pseudo of my data sending thread:
DWORD WINAPI SendDataProc(LPVOID lpParam){	OpenFile();	ReadChunkFromFile();		//incase the cancel event is triggered from outside of the thread	while(WaitForSingleObject(evtCancelTransfer, 0) != WAIT_OBJECT_0)	{		//wait for socket to be ready		WaitForSingleObject(evtSocketReady, TIMEOUT);				if(SendChunk() == BLOCKED)		{			ResetEvent(evtSocketReady);			continue;		}				if(EOF)		{			CloseFile();			break;		}		else		{			ReadNextChunk();		}	}	return 1;}


now, this thread can either return because the file transfer has completed, or it can return because evtCancelTransfer has been triggered.

I need to:
1) be able to detect whether or not a file transfer is in progress
2) be notified when a transfer ends
3) end the transfer properly at the users command

As far as the transfer ending on its own, I figured that I could put this right at the end of the thread before it returns.
PostMessage(tdata.hOwner, WM_SENDCOMPLETE, NULL, NULL);

then when handling that message, to make sure that the thread is finished,
case WM_COMPLETE:	WaitForSingleObject(hThread, INFINITE);	DoGarbageCleanupForThread();


all this would be fine and dandy if there wasn't the possibility of the transfer having to be canceled in the middle.

because if use SetEvent(evtCancelTransfer) to allow the thread to finish properly, when would I do the cleanup? That is the problem. In the lines following the cancellation, I could not safely use the resources of that thread or file transfer, because WM_SENDCOMPLETE has not yet been called to do the cleanup.

I am confused about how to handle this =/ Its kind of a paradox...
Why not have the main thread do WaitForSingleObject(hThread, 0); to see if the thread has finished, and if it has, check some variable (global state or some variable passed as the thread parameter) to find out if the transfer completed successfully or if there was an error?

The way I do these things is have the main thread create all the handles necessary, then spawn the thread and then check every now and then whether it's completed, and if so cleanup everything. Then you have one place where everything is cleaned up, either because of an error or because of the thread exiting normally.

Or, if you don't want to do any polling at all from the main thread, why not have the thread send the WM_SENDCOMPLETE message just before it exits in any circumstance (Using the thread exit code or the WPARAM or LPARAM in the message to indicate success / error code), and in your WM_SENDCOMPLETE handler, wait on the thread handle and then clean everything up?
Quote:Original post by CPPNick
1) be able to detect whether or not a file transfer is in progress

If the thread is running, a file transfer is in progress.

Quote:2) be notified when a transfer ends

The thread returns when the transfer ends (regardless of whether it finished naturally or was canceled).

Quote:3) end the transfer properly at the users command

You just signal the 'evtCancelTransfer' object. The loop will break and the thread will terminate.

You can use the thread's return value to indicate whether or not the transfer was successful. This is easy enough to detect from within the thread itself -- on EOF, return 0 instead of breaking. Unless I'm missing something, there isn't much different between the transfer completing versus being canceled from the code side.
Quote:Original post by Evil Steve
Or, if you don't want to do any polling at all from the main thread, why not have the thread send the WM_SENDCOMPLETE message just before it exits in any circumstance (Using the thread exit code or the WPARAM or LPARAM in the message to indicate success / error code), and in your WM_SENDCOMPLETE handler, wait on the thread handle and then clean everything up?


That is exactly what I am trying to do, which would work in any case except when the transfer has been canceled.

example:
SetEvent(Cancel);WaitForSingleEvent(hThread, INFINITE);TryStartAnotherTransfer(); **// Error or memory leak: the WM_SENDCOMPLETE has not yet been called// to do the cleanup. New handles will be created before closing// the old ones, or new memory will be allocated before the old// memory is free.

and then

Quote:Original post by Zipster
If the thread is running, a file transfer is in progress.


example of problem:(exaggerated time)

12:00: //12:05: GetExitCodeThread(hStreamThread, &dwExitCode);12:10: thread terminates12:15: if(dwExitCode == STILL_ACTIVE){2012:	//thread no longer exists =O}


isn't this a valid problem?
Quote:Original post by CPPNick
That is exactly what I am trying to do, which would work in any case except when the transfer has been canceled.

example:
SetEvent(Cancel);WaitForSingleEvent(hThread, INFINITE);TryStartAnotherTransfer(); **// Error or memory leak: the WM_SENDCOMPLETE has not yet been called// to do the cleanup. New handles will be created before closing// the old ones, or new memory will be allocated before the old// memory is free.
Leaving out the TryStartAnotherTransfer part for now, it should work fine, the worker thread will post a "send complete" even when it terminates, you pick up the WM_SENDCOMPLETE message and do the cleanup then.

Going back to TryStartAnotherTransfer; I'd encapsulate all of the state for one transfer into a struct, allocate it with new before spawning the new thread, and clean it up and delete it in WM_SENDCOMPLETE. You can pass the struct pointer to the thread via the thread param, and can get it back in the LPARAM of WM_SENDCOMPLETE.
Then you can have multiple threads active at once, and calling TryStartAnotherTransfer() in your above code shouldn't present any problems when another transfer is still being cleaned up.
Quote:Original post by CPPNick
example of problem:(exaggerated time)

*** Source Snippet Removed ***

isn't this a valid problem?

You want to use GetExitCodeThread after the thread terminates, which itself can be checked by using WaitForSingleObject. The return value should be valid for as long as you keep the thread handle open. This value will tell you whether the transfer was canceled or succeeded, and you can proceed from there.
That's originally what I tried to do, because the event objects example on MSDN did it that way, but then I hit a snag because the one resource that has to be reused is the socket. I didn't think I could have a completely independent thread using the same socket. One thing that I didn't think of is opening a second socket to the same user specifically for the file transfer.. is that what you would do?

edit: Zipster: I meant in the context of a task that needed to be done while the transfer was active, not once it had completed...so I think it may be possible for the exit code to report that its active, at the instant before it returns, and that by the time my app executes the code that affects the transfer, it has ended, and I get problems like closed handles because the garbage cleanup has already been done

edit2: I am starting to think that a separate socket specifically for file transfers may be the way to go, because then all of the resources for each transfer would be exclusive to that particular thread, in which case I could even have 5 file transfers going to the same user at the same time
Quote:Original post by CPPNick
That's originally what I tried to do, because the event objects example on MSDN did it that way, but then I hit a snag because the one resource that has to be reused is the socket. I didn't think I could have a completely independent thread using the same socket. One thing that I didn't think of is opening a second socket to the same user specifically for the file transfer.. is that what you would do?
That depends on your application. FTP for instance opens a new socket for each file, whereas there may be reasons to not open a new socket (E.g. if it's a server sending a file to a client on a socket the client opened).

However, if your code still calls WaitForSingleObject(hThread, INFINITE), you know that the thread has exited and therefore isn't using the socket, so it should be fine to start a new worker thread.

This topic is closed to new replies.

Advertisement