Solved

waitforsingleobject(xyz)

Posted on 2011-02-15
37
823 Views
Last Modified: 2012-05-11
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


0
Comment
Question by:mohet01
  • 17
  • 12
  • 3
  • +2
37 Comments
 

Author Comment

by:mohet01
ID: 34904268
This is windows 2003 machine
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34904292
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
0
 

Author Comment

by:mohet01
ID: 34904476
Hello
What is kernel mode APC?
Sham
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34904513
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
0
 

Author Comment

by:mohet01
ID: 34905299
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?
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34905463
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
0
 
LVL 11

Expert Comment

by:DeepuAbrahamK
ID: 34905493
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
0
 
LVL 32

Expert Comment

by:sarabande
ID: 34905665
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
0
 

Author Comment

by:mohet01
ID: 34905770
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
0
 

Author Comment

by:mohet01
ID: 34905856
Sorry guys
i will update again
Hold on !!!!!!!!!
Sham
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34905870
JFI: not everyone here is a guy :o)
0
 
LVL 8

Expert Comment

by:lomo74
ID: 34905895
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 -
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34905915
@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 ...
0
 

Author Comment

by:mohet01
ID: 34905959
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
0
 
LVL 8

Expert Comment

by:lomo74
ID: 34905972
@Zoppo: correct. I agree. I've been too hasty in copy/pasting :-)
0
 

Author Comment

by:mohet01
ID: 34906021
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
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34906046
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' ...
0
 
LVL 8

Expert Comment

by:lomo74
ID: 34906087
> 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?
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

Author Comment

by:mohet01
ID: 34906159
Hello Zoppo
Please also let me know the msdn  link which talks about the problem with pulseevent
Sham
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34906190
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 ...
0
 
LVL 11

Expert Comment

by:DeepuAbrahamK
ID: 34906370
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34906395
>> 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 ...
0
 

Author Comment

by:mohet01
ID: 34912204
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

 
0
 

Author Comment

by:mohet01
ID: 34912608
Hello
with respect to my second point in my previous update, I have a little correction here.
Please ignore this.
Sham
0
 

Author Comment

by:mohet01
ID: 34912680
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

 
0
 

Author Comment

by:mohet01
ID: 34913503
Hello
Can somebody respond to my update?
Sham
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34914001
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
0
 

Author Comment

by:mohet01
ID: 34914887
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
0
 
LVL 30

Assisted Solution

by:Zoppo
Zoppo earned 250 total points
ID: 34914951
Well,  I think it's different. IMO the system scheduler generally works based on threads, not on processes. Each process is just a bunch of one or more threads. The system scheduler assigns time slices to threads in order of there state and priority. This I think it the only way it is possible for the OS to execute several threads of one process at the same time.

Take a look here about context switching: http://msdn.microsoft.com/en-us/library/ms682105%28v=vs.85%29.aspx

ZOPPO
0
 

Author Comment

by:mohet01
ID: 34914983
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
0
 
LVL 32

Expert Comment

by:sarabande
ID: 34915017
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
0
 

Author Comment

by:mohet01
ID: 34915069
Hello
If you say this:
"each thread is independent for scheduling "

Can i see the thread id in Task manager?
Sham
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34915093
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
0
 

Author Comment

by:mohet01
ID: 34915105
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


0
 
LVL 32

Expert Comment

by:sarabande
ID: 34915116
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
0
 
LVL 30

Accepted Solution

by:
Zoppo earned 250 total points
ID: 34915134
Yes, when starting multi-threaded programming in Windows it's a very, very good idea to read MSDN's 'Processes and Threads': http://msdn.microsoft.com/en-us/library/ms684841%28v=VS.85%29.aspx

It's much to read but contains a lot essential info one has to know fro proper multi-threading programming ...
0
 

Author Closing Comment

by:mohet01
ID: 34915650
Done
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

The password reset disk is often mentioned as the best solution to deal with the lost Windows password problem. In Windows 2008, 7, Vista and XP, a password reset disk can be easily created. But besides Windows 7/Vista/XP, Windows Server 2008 and ot…
Ever notice how you can't use a new drive in Windows without having Windows assigning a Disk Signature?  Ever have a signature collision problem (especially with Virtual Machines?)  This article is intended to help you understand what's going on and…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now