Bug 981960 Retry to remove found char message with GetMessage() when PeekMessage() fails to remove the message from the queue r=jimm

This commit is contained in:
Masayuki Nakano 2014-03-12 20:04:17 +09:00
parent 262a9b4cd4
commit d74f62cf5a
2 changed files with 60 additions and 34 deletions

View File

@ -1314,6 +1314,20 @@ GetMessageName(UINT aMessage)
#endif // #ifdef MOZ_CRASHREPORTER
bool
NativeKey::MayBeSameCharMessage(const MSG& aCharMsg1,
const MSG& aCharMsg2) const
{
// NOTE: Although, we don't know when this case occurs, the scan code value
// in lParam may be changed from 0 to something. The changed value
// is different from the scan code of handling keydown message.
static const LPARAM kScanCodeMask = 0x00FF0000;
return
aCharMsg1.message == aCharMsg2.message &&
aCharMsg1.wParam == aCharMsg2.wParam &&
(aCharMsg1.lParam & ~kScanCodeMask) == (aCharMsg2.lParam & ~kScanCodeMask);
}
bool
NativeKey::GetFollowingCharMessage(MSG& aCharMsg) const
{
@ -1351,13 +1365,14 @@ NativeKey::GetFollowingCharMessage(MSG& aCharMsg) const
// the message range. So, if it returns WM_NULL, we should retry to get
// the following char message it was found above.
for (uint32_t i = 0; i < 5; i++) {
static const LPARAM kScanCodeMask = 0x00FF0000;
MSG removedMsg;
MSG removedMsg, nextKeyMsgInAllWindows;
bool doCrash = false;
if (!WinUtils::PeekMessage(&removedMsg, mMsg.hwnd,
nextKeyMsg.message, nextKeyMsg.message,
PM_REMOVE | PM_NOYIELD)) {
MSG nextKeyMsgInAllWindows;
// We meets unexpected case. We should collect the message queue state
// and crash for reporting the bug.
doCrash = true;
// The char message is redirected to different thread's window by focus
// move or something or just cancelled by external application.
if (!WinUtils::PeekMessage(&nextKeyMsgInAllWindows, 0,
@ -1365,20 +1380,29 @@ NativeKey::GetFollowingCharMessage(MSG& aCharMsg) const
PM_NOREMOVE | PM_NOYIELD)) {
return true;
}
// The char message is redirected to different window created by our
// thread.
if (nextKeyMsgInAllWindows.message == nextKeyMsg.message &&
nextKeyMsgInAllWindows.wParam == nextKeyMsg.wParam &&
(nextKeyMsgInAllWindows.lParam & ~kScanCodeMask) ==
(nextKeyMsg.lParam & ~kScanCodeMask) &&
nextKeyMsgInAllWindows.hwnd != mMsg.hwnd) {
aCharMsg = nextKeyMsgInAllWindows;
return true;
if (MayBeSameCharMessage(nextKeyMsgInAllWindows, nextKeyMsg)) {
// The char message is redirected to different window created by our
// thread.
if (nextKeyMsgInAllWindows.hwnd != mMsg.hwnd) {
aCharMsg = nextKeyMsgInAllWindows;
return true;
}
// The found char message still in the queue, but PeekMessage() failed
// to remove it only with PM_REMOVE. Although, we don't know why this
// occurs. However, this occurs acctually.
// Try to remove the char message with GetMessage() again.
if (WinUtils::GetMessage(&removedMsg, mMsg.hwnd,
nextKeyMsg.message, nextKeyMsg.message)) {
// Cancel to crash, but we need to check the removed message value.
doCrash = false;
}
}
// Otherwise, perhaps, we meet a PeekMessage()'s bug. Let's crash and
// collect the detail.
}
if (doCrash) {
#ifdef MOZ_CRASHREPORTER
nsPrintfCString info("\nHandling message: %s (0x%08X), wParam: 0x%08X, "
nsPrintfCString info("\nPeekMessage() failed to remove char message! "
"\nHandling message: %s (0x%08X), wParam: 0x%08X, "
"lParam: 0x%08X, hwnd=0x%p, InSendMessageEx()=%s, \n"
"Found message: %s (0x%08X), wParam: 0x%08X, "
"lParam: 0x%08X, hwnd=0x%p, "
@ -1426,12 +1450,10 @@ NativeKey::GetFollowingCharMessage(MSG& aCharMsg) const
// NOTE: Although, we don't know when this case occurs, the scan code value
// in lParam may be changed from 0 to something. The changed value
// is different from the scan code of handling keydown message.
if (removedMsg.message != nextKeyMsg.message ||
removedMsg.wParam != nextKeyMsg.wParam ||
(removedMsg.lParam & ~kScanCodeMask) !=
(nextKeyMsg.lParam & ~kScanCodeMask)) {
if (!MayBeSameCharMessage(removedMsg, nextKeyMsg)) {
#ifdef MOZ_CRASHREPORTER
nsPrintfCString info("\nHandling message: %s (0x%08X), wParam: 0x%08X, "
nsPrintfCString info("\nPeekMessage() removed unexpcted char message! "
"\nHandling message: %s (0x%08X), wParam: 0x%08X, "
"lParam: 0x%08X, hwnd=0x%p, InSendMessageEx()=%s, "
"\nFound message: %s (0x%08X), wParam: 0x%08X, "
"lParam: 0x%08X, hwnd=0x%p, "
@ -1489,7 +1511,8 @@ NativeKey::GetFollowingCharMessage(MSG& aCharMsg) const
return true;
}
#ifdef MOZ_CRASHREPORTER
nsPrintfCString info("\nHandling message: %s (0x%08X), wParam: 0x%08X, "
nsPrintfCString info("\nWe lost following char message! "
"\nHandling message: %s (0x%08X), wParam: 0x%08X, "
"lParam: 0x%08X, InSendMessageEx()=%s, \n"
"Found message: %s (0x%08X), wParam: 0x%08X, "
"lParam: 0x%08X, removed a lot of WM_NULL",
@ -1517,16 +1540,21 @@ NativeKey::DispatchPluginEventsAndDiscardsCharMessages() const
bool anyCharMessagesRemoved = false;
MSG msg;
while (GetFollowingCharMessage(msg)) {
if (mWidget->Destroyed()) {
MOZ_CRASH(
"NativeKey tries to dispatch a plugin event on destroyed widget");
if (msg.message == WM_NULL) {
continue;
}
anyCharMessagesRemoved = true;
// If the window handle is changed, focused window must be changed.
// So, plugin shouldn't handle it anymore.
if (msg.hwnd != mMsg.hwnd) {
break;
}
MOZ_RELEASE_ASSERT(!mWidget->Destroyed(),
"NativeKey tries to dispatch a plugin event on destroyed widget");
mWidget->DispatchPluginEvent(msg);
if (mWidget->Destroyed()) {
return true;
}
anyCharMessagesRemoved = true;
}
if (!mFakeCharMsgs && !anyCharMessagesRemoved &&
@ -1535,15 +1563,12 @@ NativeKey::DispatchPluginEventsAndDiscardsCharMessages() const
while (WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_CHAR, WM_CHAR,
PM_REMOVE | PM_NOYIELD)) {
if (msg.message != WM_CHAR) {
if (msg.message != WM_NULL) {
MOZ_CRASH("Unexpected message was removed");
}
MOZ_RELEASE_ASSERT(msg.message == WM_NULL,
"Unexpected message was removed");
continue;
}
if (mWidget->Destroyed()) {
MOZ_CRASH(
"NativeKey tries to dispatch a plugin event on destroyed widget");
}
MOZ_RELEASE_ASSERT(!mWidget->Destroyed(),
"NativeKey tries to dispatch a plugin event on destroyed widget");
mWidget->DispatchPluginEvent(msg);
return mWidget->Destroyed();
}

View File

@ -368,6 +368,7 @@ private:
{
return (aMessage == WM_SYSCHAR || aMessage == WM_SYSDEADCHAR);
}
bool MayBeSameCharMessage(const MSG& aCharMsg1, const MSG& aCharMsg2) const;
bool IsFollowedByDeadCharMessage() const;
/**