From cf8700162d1ddaa146f3273d24be2e0efa301184 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 19 Oct 2014 14:16:18 +0000 Subject: [PATCH] Fix handling of spurious wake ups in GetNextMessageTimeout() in wxMSW. It didn't take long to realize that changes of r78041 did break something (see #9053), as MsgWaitForMultipleObjects() can return indicating the message availability even if no message is actually available in the queue. This notably happens when the application is activated. Fix this by calling MsgWaitForMultipleObjects() in a loop until we do get a message. Notice that this only works correctly with the infinite timeout as we don't update the remaining time to wait after a spurious wake-up, but this shouldn't be a problem in practice as no such wake-ups should happen anyhow during a small timeout duration -- and nobody typically uses long ones. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@78047 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/msw/evtloopconsole.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/msw/evtloopconsole.cpp b/src/msw/evtloopconsole.cpp index 5c56fbbd07..59ea8f01f8 100644 --- a/src/msw/evtloopconsole.cpp +++ b/src/msw/evtloopconsole.cpp @@ -102,10 +102,7 @@ int wxMSWEventLoopBase::GetNextMessageTimeout(WXMSG *msg, unsigned long timeout) // MsgWaitForMultipleObjects() won't notice any input which was already // examined (e.g. using PeekMessage()) but not yet removed from the queue // so we need to remove any immediately messages manually - // - // NB: using MsgWaitForMultipleObjectsEx() could simplify the code here but - // it is not available in very old Windows versions - if ( !::PeekMessage(msg, 0, 0, 0, PM_REMOVE) ) + while ( !::PeekMessage(msg, 0, 0, 0, PM_REMOVE) ) { DWORD rc = ::MsgWaitForMultipleObjects ( @@ -131,17 +128,12 @@ int wxMSWEventLoopBase::GetNextMessageTimeout(WXMSG *msg, unsigned long timeout) // return to the event loop, so pretend there was WM_NULL in // the queue. wxZeroMemory(*msg); - break; + return TRUE; case WAIT_OBJECT_0 + 1: - // Some message is supposed to be available. - if ( !::PeekMessage(msg, 0, 0, 0, PM_REMOVE) ) - { - // somehow it may happen that MsgWaitForMultipleObjects() - // returns true but there are no messages -- just treat it - // the same as timeout then - return -1; - } + // Some message is supposed to be available, but spurious + // wake ups are also possible, so just return to the loop: + // either we'll get the message or start waiting again. break; } }