how windows detects hung window ?

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi All,

I am little confused here, hope you can help me.

While processing WM_POWERBROADCAST
(wParam=PBT_APMQUERYSUSPEND), I MUST to do some lengthy
operation(30 sec) before system Suspends or hibernates. To
achieve this, in my message handler when processing
PBT_APMQUERYSUSPEND, I create another thread which takes
care of making this lengthy operation, and when its done I
set event to PBT_APMQUERYSUSPEND message processor(while
it is in WaitForSinleObject), that work was finished and
now can allow windows to suspend/hibernate. The problem is
that when processing PBT_APMQUERYSUSPEND while on
WaitForSinleObject, windows doesn't waits for me to return
value and proceeds with suspend/hibernation. The weird
thing I don't understand is that if I call only MessageBox
() in my PBT_APMQUERYSUSPEND handler, the windows waits
until I press OK, even if I do so after 10 minutes.

So I don't understand why, windows doesn't think my thread
is hung when I call MessageBox and does think its hung
when I have WaitForSingleObject.


I even tried putting PeekMessage that removes all the
messages from window queue and call Sleep(100) , to try
tell windows that I am not hung, but it still resumes with
suspend/hibernation.

Another thing is that, documentation says that it will
wait only 20 seconds until "thinking" my thread is hung if
I don't remove WM_POWERBROADCAST from my message queue,
but I do remove it and do WaitForSingleObject, still it
continues with suspend/hibernation.

(The operation that I should do before suspend/hibernate
is vital, so please don't suggest other things instead..)

Hope some one can help me.

Thanks
 
While processing WM_POWERBROADCAST
(wParam=PBT_APMQUERYSUSPEND), I MUST to do some lengthy
operation(30 sec) before system Suspends or hibernates. To
achieve this, in my message handler when processing
PBT_APMQUERYSUSPEND, I create another thread which takes
care of making this lengthy operation, and when its done I
set event to PBT_APMQUERYSUSPEND message processor(while
it is in WaitForSinleObject), that work was finished and
now can allow windows to suspend/hibernate. The problem is
that when processing PBT_APMQUERYSUSPEND while on
WaitForSinleObject, windows doesn't waits for me to return
value and proceeds with suspend/hibernation.

I'm not sure I understand what you are doing. If you are creating a
background thread only to wait on it synchronously in the UI thread, it
seems to me that you might as well just do the lengthy processing the the UI
thread. No matter, that won't solve your problem.
The weird
thing I don't understand is that if I call only MessageBox
() in my PBT_APMQUERYSUSPEND handler, the windows waits
until I press OK, even if I do so after 10 minutes.

Windows' heuristic to detect a hung application is to send it an innocuous
WM_NULL message. If it does not get back a reply (most often from with
DefWindowProc() ) then it assumes the application is not hung.
So I don't understand why, windows doesn't think my thread
is hung when I call MessageBox and does think its hung
when I have WaitForSingleObject.

That's because MessageBox() spins a message loop, dispatching messages while
the dialog is displayed.
I even tried putting PeekMessage that removes all the
messages from window queue and call Sleep(100) , to try
tell windows that I am not hung, but it still resumes with
suspend/hibernation.

It is not CPU utilization that Windows uses to detect a hung happlication.
Hope some one can help me.

Yes. Instead of WaitForSingleObject(), use MsgWaitForMultipleObjects() in a
loop. When your background thread completes exit the loop. While the
background thread is running, if the function indicates that you have a
message waiting then process it so Windows knows that you are busy. Read the
help entry for the function carefully, you must drain the queue of messages
before you begin the next wait.

Regards,
Will
 
William DePalo said:
Yes. Instead of WaitForSingleObject(), use MsgWaitForMultipleObjects() in a
loop. When your background thread completes exit the loop. While the
background thread is running, if the function indicates that you have a
message waiting then process it so Windows knows that you are busy. Read the
help entry for the function carefully, you must drain the queue of messages
before you begin the next wait.

Will,

Would the AtlWaitWithMessageLoop function be a good example of doing this?
If so, it's (available as) an inline with source provided.
 
See if SendMessageTimeout helps you. I think this is how windows internally figures out
which process is hung.

--
Ajay Kalra [MVP - VC++]
(e-mail address removed)


| Hi All,
|
| I am little confused here, hope you can help me.
|
| While processing WM_POWERBROADCAST
| (wParam=PBT_APMQUERYSUSPEND), I MUST to do some lengthy
| operation(30 sec) before system Suspends or hibernates. To
| achieve this, in my message handler when processing
| PBT_APMQUERYSUSPEND, I create another thread which takes
| care of making this lengthy operation, and when its done I
| set event to PBT_APMQUERYSUSPEND message processor(while
| it is in WaitForSinleObject), that work was finished and
| now can allow windows to suspend/hibernate. The problem is
| that when processing PBT_APMQUERYSUSPEND while on
| WaitForSinleObject, windows doesn't waits for me to return
| value and proceeds with suspend/hibernation. The weird
| thing I don't understand is that if I call only MessageBox
| () in my PBT_APMQUERYSUSPEND handler, the windows waits
| until I press OK, even if I do so after 10 minutes.
|
| So I don't understand why, windows doesn't think my thread
| is hung when I call MessageBox and does think its hung
| when I have WaitForSingleObject.
|
|
| I even tried putting PeekMessage that removes all the
| messages from window queue and call Sleep(100) , to try
| tell windows that I am not hung, but it still resumes with
| suspend/hibernation.
|
| Another thing is that, documentation says that it will
| wait only 20 seconds until "thinking" my thread is hung if
| I don't remove WM_POWERBROADCAST from my message queue,
| but I do remove it and do WaitForSingleObject, still it
| continues with suspend/hibernation.
|
| (The operation that I should do before suspend/hibernate
| is vital, so please don't suggest other things instead..)
|
| Hope some one can help me.
|
| Thanks
|
 
Even better, just post a message from the processing thread back to your
window when done. Run a message loop waiting for that message.

MsgWaitForMultipleObjects is tricky sometimes.
 
Jeff Partch said:
Would the AtlWaitWithMessageLoop function be a good example of doing this?
If so, it's (available as) an inline with source provided.

I didn't scrutinize the source but, for the O.P. it would seem a good place
to start as some source is better than no source.

Regards,
Will
 
So I don't understand why, windows doesn't think my thread
is hung when I call MessageBox and does think its hung
when I have WaitForSingleObject.

Windows expects a thread to pump messages. If it doesn't accept a
message for a while it is presumed "hung." The answer to your
puzzlement is that MessageBox continues to pump messages,
WaitForSingleObject does not.
 
William, thanks a lot for your reply.
I'm not sure I understand what you are doing. If you are creating a
background thread only to wait on it synchronously in the UI thread, it
seems to me that you might as well just do the lengthy processing the the UI
thread. No matter, that won't solve your problem.

Of course you right in this case, I forgot to mention that at some
point I change WaitForSingleObject to PeekMessage loop.

Windows' heuristic to detect a hung application is to send it an innocuous
WM_NULL message. If it does not get back a reply (most often from with
DefWindowProc() ) then it assumes the application is not hung.

Thats the thing, I don't get even WM_NULL, so can't understand how
windows senses I am hung.
It is not CPU utilization that Windows uses to detect a hung happlication.

The code of PeekMessage and Sleep(100) I had inside infinie loop for
testing, I still don't understand why I was considered hung even
though I was draining message queue with PeekMessage.

Yes. Instead of WaitForSingleObject(), use MsgWaitForMultipleObjects() in a
loop. When your background thread completes exit the loop. While the
background thread is running, if the function indicates that you have a
message waiting then process it so Windows knows that you are busy. Read the
help entry for the function carefully, you must drain the queue of messages
before you begin the next wait.

THANKS! this works great, actually I am using AtlWaitWithMessageLoop
as suggested by Mr.Jeff Partch. But I still would be glad if you could
clear above points to me.


Huge thanks !
 
Dear Jeff,
Would the AtlWaitWithMessageLoop function be a good example of doing this?
If so, it's (available as) an inline with source provided.

Thanks a lot, this was exactly what I was looking for.
 
anonymous said:
Thats the thing, I don't get even WM_NULL, so can't understand how
windows senses I am hung.

Well, you may not know that you are getting the message. :-)

If a message is sent (not posted!) to one of the windows in a thread, the
sender blocks until the thread that owns the receiving window signals that
it is idle by calling GetMessage(). At that point, GetMessage() will quietly
dispatch the window procedure of the target window, passing it the sent
message. Then it returns the result of the processing to to the sender. Then
it goes back to waiting on another sent or posted message.

I'd be willing to wager a (very) small sum that you'd see the WM_NULL
message if you set a breakpoint in the window procedure of the target
window.
The code of PeekMessage and Sleep(100) I had inside
infinie loop for testing, I still don't understand why I was
considered hung even though I was draining message
queue with PeekMessage.

Well, that's because there is no easy way to detect the hung state. One the
one hand, you can make the case that an application that idling constantly
at 0% of CPU is hung because it is doing nothing useful. And one at 100% of
CPU utilization may be considered hung if it does not respond to user input.
So, for better or worse, CPU utilization doesn't figure into the
determination. Rather, since windowed applications should be interactive,
they are considered hung if they do not interact with other applications or
Windows itself by responding to messages.

Finally, as a sidebar, note that this business of detecting of "hung"
applications by sending Windows messages, falls flat where non-interactive
applications are concerened.

Regards,
Will
 
Hi Alexander,
Even better, just post a message from the processing thread back to your
window when done. Run a message loop waiting for that message.

MsgWaitForMultipleObjects is tricky sometimes.

Yes, sending a message is much simpler thanks for the tip, I was going
to send message but then I was pointed to AtlWaitWithMessageLoop by
Jeff, which simplifies MsgWaitForMultipleObjects.

Thanks a lot
 
Hi William, thank you so much for the help.

I am still in a little blur, hope you can make things clear to me.
If a message is sent (not posted!) to one of the windows in a thread, the
sender blocks until the thread that owns the receiving window signals that
it is idle by calling GetMessage(). At that point, GetMessage() will quietly
dispatch the window procedure of the target window, passing it the sent
message. Then it returns the result of the processing to to the sender. Then
it goes back to waiting on another sent or posted message.

What do you mean by "GetMessage() will quietly dispatch the window
procedure of the target window" ? Isn't DispatchMessage the one that
dispatches the messages to window proc ?
Well, that's because there is no easy way to detect the hung state. One the
one hand, you can make the case that an application that idling constantly
at 0% of CPU is hung because it is doing nothing useful. And one at 100% of
CPU utilization may be considered hung if it does not respond to user input.
So, for better or worse, CPU utilization doesn't figure into the
determination. Rather, since windowed applications should be interactive,
they are considered hung if they do not interact with other applications or
Windows itself by responding to messages.

I was not trying to signal windows I am not hung by being on 0% cpu, I
thought that if windows will see my queue is empty it will think the
thread is responsive. The mistake I made was that I was peeking
messages only for dialogs main window(dialog mfc app), once I spot
that mistake and changed that PeekMessage get all the messages I can
suspend the suspend/hibernation process for as long as I want. But
still don't understand the heuristics that windows use to detect
window is responsive. Is it empty message queue for the thread ?

I checked with Spy++(main window + all the children) and I didn't
receive WM_NULL message, so maybe its really a matter of message queue
status ?


Thanks a lot William for your help, my main goal was accomplished but
just trying to understand it as deepe as possible
 
Hello Scott,
Windows expects a thread to pump messages. If it doesn't accept a
message for a while it is presumed "hung." The answer to your
puzzlement is that MessageBox continues to pump messages,
WaitForSingleObject does not.

Yes you are right about that. What I still don't understand is that
even thought I had a message pump for *main window
only(PeekMessage(,m_hWnd,,)* I was still considered as hung
and suspend/hibernation would start after 20 seconds. Once I changed
the message pump to get all the messages everything start to work
well. So does it mean that windows was smart and didn't just check if
I drain main window messages but also all the children ?

Thank you
 
anonymous said:
What do you mean by "GetMessage() will quietly dispatch the window
procedure of the target window" ? Isn't DispatchMessage the one that
dispatches the messages to window proc ?

Messages can be sent (with SendMessage) or posted (with PostMessage).
PostMessage always puts the message into the thread's message queue and
returns immediately. The primary function of GetMessage is to retrieve
the first message in the message queue and fill MSG struct with its
data. Then DispatchMessage is used to actually dispatch the message to
the target window proc.

SendMessage behaves differently depending on whether it's called within
the same thread or between threads. When called intra-thread, it simply
calls the target window proc directly, and returns with whatever the
window proc returns. When called inter-thread, it tries to simulate this
behavior as closely as possible. So it puts a message in a separate
queue of sent messages in the target thread, and waits for it to be
processed. Now, when the target thread calls GetMessage, the first thing
it does is it goes through sent messages queue and for each messge calls
the target window proc (note - no DispatchMessage involved, at least not
explicitly), then signals the waiting SendMessage that the message was
processed (and provides the LRESULT). Only after sent messages queue is
exhausted, GetMessage retrieves the first message from regular message
queue (containing posted messages) and returns normally (or doesn't, if
message queue is empty).

Thus, sent messages are handled transparently, you don't need to (and
can't) explicitly dispatch them.
--
With best wishes,
Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken
 
Thanks a lot Mr.Tandetnik, I didn't know that now all messages need to
be dispatched by DispatchMessage. Do you think in case of
WM_POWERBROADCAST windows decides if window is hung by checking if its
message queu is empty ? cause I don't get any WM_NULL messages and out
of curiosity want to know this.

Anyway, thank you very much about SendMessage/PostMessage explanation.
 
Back
Top