Rakesh Agarwal
Rakesh Agarwal

Reputation: 3059

WaitForSingleObject( )

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

Answers (7)

Hasturkun
Hasturkun

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

martsbradley
martsbradley

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

Test
Test

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

Fauxcuss
Fauxcuss

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

Peter Ruderman
Peter Ruderman

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

Alan Moore
Alan Moore

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

aJ.
aJ.

Reputation: 35450

I don't see any issues in the code (Assuming event is created before the thread is started in constructor).

  • The event is a auto reset event and the initial state is non signaled.
  • Child thread has to wait until the event is signaled.
  • Main thread will signal the event and waits for child process to terminate.

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

Related Questions