2
votes

We have a MFC Visual-C++ application that is not reacting to any user input.

(Note: Currently only known on one machine. The behavior does recur occasionally, but only after the App has been running for several days!)

The application is redrawn when we switch to it via Alt-Tab (or the Task Bar), but we cannot, for example, activate it's main window by clicking on the title bar.


We have already pulled 4 dumps with WinDbg and checked the active instructions. We always were in some redraw code or somesuch inside the main thread (the GUI thread). We definitely were/are not in a modal message loop and the main thread's stack always looked "OK". (Most/all worker threads were idling, waiting for some event, no suspicious code there either.)


When investigating the problem with Spy++, we see the behavior specified also in this separate question, namely that we seem to get paint and activation messages, but no user input is routed to the application. When I have the application window on the screen, and select it to show messages of the main window,

App Main Window

it will only show "generic" "referesh" messages and nothing else

Messages for the main Window

If I drill deeper, and select all messages for the whole process,

Windows of same process setting

this is what we see:

200 WM_PAINT messages per second

The app is apparently only processing messages on one hidden sub-window (00CB09F0), and what we see there is a constant stream of 200 WM_PAINT messages per second.

Normally this Sub Window isn't processing any messages at all (except refresh WM_PAINT etc. when Windows sends them). It is normally used as a drawing area and the drawing happens through a WM_TIMER message on it's parent (010A09B8) window. (This WM_TIMER message isn't shown on the hanging app either though.)

The performance profile as shown in process explorer looks like this (100% kernel time, more or less):

Process Explorer App Performance Graph

2

2 Answers

0
votes

I'd say that you have a redraw loop in that window that receives the WM_PAINT flood.

That usually happens if you call Invalidate or similar from the processing of the WM_PAINT message, directly or indirectly.

Other posibility is that, since you say that you are using a timer to redraw the window, the actual drawing is taking more time that the time it self, so the messages pile up in the queue.

Yet another posibility is that you are invalidating the window from a different thread than the one making the painting.

Anyway, you should ensure that you are calling Invalidate*() properly (you showed no code), and never from the OnPaint event. And avoid calling UpdateWindow() as this function can mess things if called without a little care.

0
votes

I've seen this problem when an exception is thrown from a dialog. MFC's DoModal function disables the main program window then reenables it when the dialog returns; exceptions bypass the reenabling part and the main window remains disabled forever.