Reputation: 3059
I have got myself stuck into a really amazing issue here.The code is like as below.
class A
{
public:
A(){
m_event = CreateEvent(NULL, false, false, NULL); // create an event with initial value as non-signalled
m_thread = _beginthread(StaticThreadEntry, 0, this); // create a thread
}
static void StaticThreadEntry(A * obj) { obj->ThreadEntry(); }
void ThreadEntry();
};
void A::ThreadEntry()
{
WaitforSingleObject(m_event,INFINITE);
}
int main()
{
A a;
SetEvent(m_event); // sets the event to signalled state which causes the running thread to terminate
WaitForSingleObject(m_thread, INFINITE); // waits for the thread to terminate
return 0;
}
Problem :
When the above code is run,sometimes( 1 out of 5 ) it hangs and the control gets stuck in the call to WaitforSingleObject()( inside the main function ).The code always calls SetEvent() function to ensure that the thread would terminate before calling Wait() function.
I do not see any reason why it should ever hang?
Upvotes: 3
Views: 44799
Reputation: 36402
you might want to consider using SignalObjectAndWait instead of the seperate SetEvent()
and WaitForSingleObject()
calls, as this occurs as a single operation, and would fail immediately if the event could not be signaled.
Upvotes: 1
Reputation: 158
Is it not bad practice to hand out the address of an object prior to that object being fully constructed. We have control of when the new thread will execute obj->ThreadEntry()
, it may be after the constructor has completed, there is a full object on which to call ThreadEntry, or ThreadEntry may begin prior to the object being constructed.
Upvotes: 0
Reputation: 19
The thread will hang if SetEvent
executes before WaitforSingleObject
in the thread. So in that case WaitforSingleObject(m_event,INFINITE)
will wait forever.
Upvotes: 1
Reputation: 468
Hasturkun says that SignalObjectAndWait is an atomic operation.
However, MSDN disagrees:
Note that the "signal" and "wait" are not guaranteed to be performed as an atomic operation. Threads executing on other processors can observe the signaled state of the first object before the thread calling SignalObjectAndWait begins its wait on the second object.
Ya, I'm a little confused myself and my head hurts right now, but I'm sure I'll figure it out. It may not be atomic, but it appears to say that it accomplishes making sure that your thread is waiting on the object before the object to be signaled is signaled. Right?
Upvotes: 0
Reputation: 12485
The problem is your use of the _beginthread API. You cannot use the handle returned from this function with the Win32 wait functions. You should use _beginthreadex or CreateThread. From MSDN:
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...
You are ... able to use the thread handle returned by _beginthreadex with the synchronization APIs, which you cannot do with _beginthread.
Upvotes: 18
Reputation: 1823
Have you checked whether the thread handle m_thread is actually valid?
There are circumstances where _beginthread will return an invalid handle - particularly when the thread exits quickly (which certainly could be the case here as the thread could spin up, pass through the wait (as the event is already set) and then terminate).
Use _beginthreadex instead to create the handle, although you would have to call _endthreadex to make sure everything was cleaned up.
Upvotes: 1
Reputation: 35450
I don't see any issues in the code (Assuming event is created before the thread is started in constructor).
Assuming this is the complete code (not the sample code ), it looks quite fine to me.
I suggest you to use process Explorer to observe the state of the event.
EDIT:
There is a slight chance that child thread gets terminated before the main thread waits on the thread handle. If the handle is reused for some other kernel objects and main thread will wait infinitely. Try duplicating the handle using DuplicateHandle after thread creation and use this handle in WaitForSingleObject.
Upvotes: 3