Link to home
Start Free TrialLog in
Avatar of mohet01
mohet01Flag for India

asked on

waitforsingleobject(xyz)

Hello
1) waitforsingleobject(xyz) is not unblocking in our c/C++ code written in Visual Studio .NET2003 IDE.
2) We basically unblock using PulseEvent(xyz) ot SetEvent(xyz) windows api
3) We know that PulseEvent(xyz) is getting executed in our application, but waitforsingleobject(xyz) is not unblocking

Please let me know, How do i analyse this scenario? Do i need to check any Windows service on the machine?


Sham


Avatar of mohet01
mohet01
Flag of India image

ASKER

This is windows 2003 machine
Avatar of Zoppo
Hi mohet01,

maybe the event is already in signaled state. How is the even object created? Is 'bInitialState' passed to CreateEvent TRUE? Is it a manual-reset event object?

One thing about PulseEvent - in MSDN you can find this statement:

A thread waiting on a synchronization object can be momentarily removed from the wait state by a kernel-mode APC, and then returned to the wait state after the APC is complete. If the call to PulseEvent occurs during the time when the thread has been removed from the wait state, the thread will not be released because PulseEvent releases only those threads that are waiting at the moment it is called. Therefore, PulseEvent is unreliable and should not be used by new applications.


So it seems to be better to use SetEvent and, in case it is a manual-reset event object, ResetEvent ...

Hope that helps,

ZOPPO
Avatar of mohet01

ASKER

Hello
What is kernel mode APC?
Sham
IMO it's not really important here what a kernel mode APC is, the interesting thing is that it can prevent a waiting thread from being signaled with PulseEvent.

BTW, here you can find info about what kernel mode APCs are: http://msdn.microsoft.com/en-us/library/ms681951%28v=vs.85%29.aspx

ZOPPO
Avatar of mohet01

ASKER

Hello
Scenario is as shown below:
Thread 1:---------------------------------
m_event=CreateEvent(0,TRUE,0,0);
While(1)
{
......
if(waitforsingleobject(m_event,INFINITE);
.....
SetEvent(m_hNotificationSyncEvent);
}
/////////////////////////////////////////////////////////


Thread2:-------------------------------------
m_hNotificationSyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
For loop
{
PulseEvent(m_event);
waitforsingleobject(m_hNotificationSyncEvent,INFINITE);
}
/////////////////////////////////////////

Do you think SetEvent() and ResetEvent() will work in this scenario?
Because PulseEvent() is being called mulitple times from Thread2, atleast once, Thread1 should catch the event, right?
Hm, I cannot grant that the PulseEvent is the real problem since I don't know when/how the threads are startet.

But, on one hand MSDN clearly says: Note This function is unreliable and should not be used. It exists mainly for backward compatibility.

On the other hand I could image one way of execution flow which may not work in your program:

Both threads are started. For any reason the 'PulseEvent' in thread 2 is called before the 'WaitForSingleObject' in thread 1 - in this case after 'PulseEvent' returned the m_event again is in no-signaled state, thus the 'WaitForSingleObject' in thread 1 never terminates, so the 'SetEvent' in thread 1 is never called so even the 'WaitForSingleObject' in thread 2 never returns. If this is the case in my opinion you should see in the debugger that both threads are waiting for 'WaitForSingleObject' calls.

I think if you do it somehow like this it could work:

Thread 1:---------------------------------
m_event=CreateEvent(0,TRUE,0,0);
While(1)
{
......
if(waitforsingleobject(m_event,INFINITE);
.....
ResetEvent( m_event );
SetEvent(m_hNotificationSyncEvent);
}
/////////////////////////////////////////////////////////


Thread2:-------------------------------------
m_hNotificationSyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
For loop
{
SetEvent(m_event);
waitforsingleobject(m_hNotificationSyncEvent,INFINITE);
ResetEvent(m_hNotificationSyncEvent); // I don't know if you simply missed this or if it's intended to set the 'm_hNotificationSyncEvent' to signaled state only once
}


It might be it's better to use auto-reset event objects instead - especially if one of the threads is intended to be multiple times simultaneously, because in this case a auto-reset event can be better used to control that i.e. always just one waiting thread 1 continues after 'SetEvent' in thread 2, then that thread 1 sets the 'm_hNotificationSyncEvent' which again only signals one waiting thread 2 a.s.o. - and further you can leave out the 'ResetEvent' calls.

Hope that helps,

ZOPPO
According to MSDN,

PulseEvent Function

Sets the specified event object to the signaled state and then resets it to the nonsignaled state after releasing the appropriate number of waiting threads.

Note  This function is unreliable and should not be used. It exists mainly for backward compatibility. For more information, see Remarks.

Read on:
http://msdn.microsoft.com/en-us/library/ms684914%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/ms682052%28v=vs.85%29.aspx
from your pseudocode the problem also can be that m_event wasn't created when 2nd thread calls PulseEvent. then both threads were waiting infinitely on their event.

you could start the second thread from thread1 after the m_event was created to make sure that the event is valid.

Sara
Avatar of mohet01

ASKER

Hello
Sorry for the inconvenience, Below is the exact scenario(x can be 0 or 1)
Binary goes in a hang state with the below threads, Which situation would create hang state?

Thread 1:---------------------------------
m_event=CreateEvent(0,TRUE,0,0);
While(1)
{
......
if (x  || WaitForSingleObject(m_event,INFINITE)==WAIT_OBJECT_0)
.....
SetEvent(m_hNotificationSyncEvent);
}
/////////////////////////////////////////////////////////


Thread2:-------------------------------------
m_hNotificationSyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
For loop
{
PulseEvent(m_event);
waitforsingleobject(m_hNotificationSyncEvent,INFINITE);
}
/////////////////////////////////////////


Sham
Avatar of mohet01

ASKER

Sorry guys
i will update again
Hold on !!!!!!!!!
Sham
JFI: not everyone here is a guy :o)
sarabande is correct.
the order you create the two threads is relevant, because thread1 sets m_hNotificationSyncEvent (which is created by thread2), and thread2 pulses m_event (which is created by thread1).
suppose thread2 tries to pulse m_event *before* thread1 could create the event: deadlock.
I suggest that you create the two synchronization objects outside of the threads, then start the two threads:

m_event=CreateEvent(NULL, TRUE, FALSE, NULL);
m_hNotificationSyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
CreateThread(NULL, 0, &thread1, NULL, 0, NULL);
CreateThread(NULL, 0, &thread2, NULL, 0, NULL);

Thread 1:---------------------------------
While(1)
{
......
if (x  || WaitForSingleObject(m_event,INFINITE)==WAIT_OBJECT_0)
.....
SetEvent(m_hNotificationSyncEvent);
}
/////////////////////////////////////////////////////////

Thread2:-------------------------------------
For loop
{
PulseEvent(m_event);
waitforsingleobject(m_hNotificationSyncEvent,INFINITE);
}
/////////////////////////////////////////

- Lorenzo -
@lomo74
even with this code it is possible that 'PulseEvent(m_event);' in thread 2 is called before 'WaitForSingleObject(m_event,INFINITE)' which will lead to deadlock too as I described above.

I think we should all agree that 'PulseEvent' shouldn't be used ...
Avatar of mohet01

ASKER

Hello
Sorry for the inconvenience, Below is the exact scenario(x can be 0 or 1)
Binary goes in a hang state with the below threads, Which situation would create such hang state?

Thread 1:---------------------------------
m_event=CreateEvent(0,TRUE,0,0);
While(1)
{
......
/*x is accessed here on mutex y*/
if (x || WaitForSingleObject(m_event,INFINITE)==WAIT_OBJECT_0)
.....
SetEvent(m_hNotificationSyncEvent);
}
/////////////////////////////////////////////////////////


Thread2:-------------------------------------
m_hNotificationSyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
/*x will get accessed using some mutex y and get modified in this thread2 to value 0 or 1*/
For loop
{
PulseEvent(m_event);
waitforsingleobject(m_hNotificationSyncEvent,INFINITE);
}
/////////////////////////////////////////

Am sorry guys for this repetition.
Please bear with me.
Sham
@Zoppo: correct. I agree. I've been too hasty in copy/pasting :-)
Avatar of mohet01

ASKER

m_event and m_hNotificationSyncEvent are created in their corresponding class constructors.
But these two are member of therir corresponding classes in their own header files which are visible to all threads
Thread1 is part of one class
Thread2 is part of anoher class

Sham
In other words: you mean the event objects are created before the threads were started?

Then IMO only the 'PulseEvent' problem can cause the hang - except maybe I misunderstand something; I think the code now is harder to understand since I have no idea what you really mean with that 'x' and 'y' ...
> m_event and m_hNotificationSyncEvent are created in their corresponding class constructors.
> But these two are member of therir corresponding classes in their own header files which are visible to all threads

but in your pseudocode, m_event and m_hNotificationSyncEvent are created inside thread1 and thread2, respectively.
besides this, the issue is not about visibility but *availability* of sync objects.
in other words can you ensure that m_event and m_hNotificationSyncEvent *exist* at the time thread1 or thread2 try to use them?
Avatar of mohet01

ASKER

Hello Zoppo
Please also let me know the msdn  link which talks about the problem with pulseevent
Sham
It's the same DeepuAbrahamK posted above: http://msdn.microsoft.com/en-us/library/ms684914%28v=vs.85%29.aspx - see the Remarks section there ...
>> alternative for pulseevent
about these Condition Variables functionality shown at the given link you have to take into consideration that it's only available with Windows Vista and Windows Server 2008 or higher ...
Avatar of mohet01

ASKER

Hello
1) In the core dump that I analysed, I see that  both the threads are waiting on waitforsingleobject().
2) I agree zoppo, that pulseevent should be replaced but setevent() and resetevent() would work only if thread1 is the only thread which is actually using m_event, am I correct.
3) I also agree with sara that createevent for 2 sync var should get executed before threads start, if they are in two different classes, obviously and obviously we can say this is the problem,correct?
4) another point I observed that you people respond very interestingly for such topics, unlike other queries which I feel are also interesting.
Sham

 
Avatar of mohet01

ASKER

Hello
with respect to my second point in my previous update, I have a little correction here.
Please ignore this.
Sham
Avatar of mohet01

ASKER

Hello
To recorrect my second point, I would like to ask this question:
 windows os scheduler can schedule my c++ binary as a process only, os scheduler does not know if a process is single/multiple threaded. thread scheduler code of my c++ binary runtime code has to share that  time among the threads of the binary, if this is correct, then,
I would like to know that waitforsingleobject(m-event) of thread1 makes the thread go into a state, which is similar to thread scheduler placing the thread into wait state?
based on the answer I will get to the current deadlock problem.
Sham

 
Avatar of mohet01

ASKER

Hello
Can somebody respond to my update?
Sham
Hi again,

first to one statement you gave above:

>> 2) I agree zoppo, that pulseevent should be replaced but setevent() and resetevent() would work only if thread1 is the only thread which is actually using m_event, am I correct.

I think there may be a general problem with your design: As far as I understand the code you posted there are two different thread procedures which are synchronized where Thread2 causes a Thread1 to proceed anything while Thread2 is waiting for Thread1 to finish it's current processing - after this Thread2 again 'starts' Thread1 a.s.o., just like ping pong ...

Now how to implement depends on your needs - if you need multiple Thread1s with this there are problems: Using SetEvent for m_event will behave different depending on the fact whether it's a manual reset or a auto reset event:

1. auto reset event: When signaled by Thread2 any one of the running Thread1s starts processing since WaitForSingleObject returns - the event is automatically reset, so no other Thread1 starts processing. After the running Thread1 executed it's processing it sets the m_hNotificationSyncEvent so Thread2 can continue - so Thread2 again sets the event thus signaling another Thread1 (which even can be the same as before), a.s.o.

With this you can only let one Thread1 do its processing at a time.

2. manual reset event: When signaled by Thread2 every Thread1 starts processing as long as no ResetEvent is called for m_event before all Thread1's WaitForSingleObject returned. The problem here is that single threads may loop multiple times since as long as m_event isn't reset every Thread1's WaitforSingleObject return at once. Another problem is that setting m_hNotificationSyncEvent from any Thread1 signals Thread2 to continue.

With this it's not really possible to synchronize one or more Thread2 with multiple Thread1s.


So, you already see it's hard to say how this should be implemented as long as we don't know what you want to achieve with your code.


>> windows os scheduler can schedule my c++ binary as a process only, os scheduler does not know if a process is single/multiple threaded.

This IMO isn't correct - the OS scheduler shcedules single threads, not processes - otherwise it wouldn't be possible that multiple threads of one process run simultaneously on different CPUs/-cores. The C-runtime hasn't much to do with it.


As a conclusion I would suggest you explain what your application should do or how you intend the threads to work.


ZOPPO
Avatar of mohet01

ASKER

Hello
I would like to first confirm my point on Scheduling part and then i would like to switch to actual question.
In the below para, a thread mean, invoking createthread() api with a function name as argument.
"I wrote a Windows c/c++ app whose binary is scheduled as a process(say process id 1234), Windows OS scheduler schedules this process 1234, OS scheduler does not know whether process 1234 is single/multiple threaded. When OS scheduler gives say 5 msec to this process 1234, _init()function[linker adds this platform specific code during link time]  of process 1234 has thread scheduler logic which internally schedules each thread of that process within 5 msec "

Am i correct?

Sham
SOLUTION
Avatar of Zoppo
Zoppo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mohet01

ASKER

Hello
if a process code invokes createthread() api with a function name, then a new thread gets scheduled in a run queue of OS scheduler?
Sham
zoppo is right. even for a single-threaded app the scheduler operates on main thread of the process and not on the process itself.

after you started more threads each thread is independent for scheduling beside that it could get default priority from main thread. but that can be changed individually for each thread and is also dependent on what the thread does. if it does i/o it gets much much less processor time than it would get with an infinite loop and doing some math. or better said each i/o statement would cause the thread to get paused. when threads were suspended cause they were waiting for event, the scheduler won't see them until they were awaked after the event was signaled.

Sara
Avatar of mohet01

ASKER

Hello
If you say this:
"each thread is independent for scheduling "

Can i see the thread id in Task manager?
Sham
Hi,

you cannot see the thread IDs in windows task manager, but there are tools where you can, IMO the best is SysInternals Process Explorer, there you can see info about all threads running for a single process - you can download this tool here: http://technet.microsoft.com/en-us/sysinternals/bb896653

ZOPPO
Avatar of mohet01

ASKER

Hello Zoppo
May be i need to go through processes and threads in your provided link: http://msdn.microsoft.com/en-us/library/ms682105%28v=vs.85%29.aspx

This would clarify all the junk confusion that i have, right?
Sham


no, the Windows Task Manager monitors processes. but you could add the the number of threads for a process as a new column.

if you want to monitor your threads you could log messages to shared memory from your threads including the thread-id (or a letter for each thread id).

you also could write to log-file but that has bigger influence on scheduling behavior than writing to memory.

Sara
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mohet01

ASKER

Done