Bug 545338 - RPCChannel should use events rather than thread messages for NotifyWokerThread. r=bent.
This commit is contained in:
@@ -103,9 +103,6 @@ using namespace mozilla::ipc::windows;
|
||||
|
||||
namespace {
|
||||
|
||||
UINT gEventLoopMessage =
|
||||
RegisterWindowMessage(L"SyncChannel Windows Message Loop Message");
|
||||
|
||||
UINT gOOPPSpinNativeLoopEvent =
|
||||
RegisterWindowMessage(L"SyncChannel Spin Inner Loop Message");
|
||||
|
||||
@@ -590,13 +587,17 @@ TimeoutHasExpired(const TimeoutData& aData)
|
||||
// at the base of the stack. To accomplish this, we use a second counter to
|
||||
// limit the number of calls to SpinInternalEventLoop() equal to the number
|
||||
// of modal loops entered.
|
||||
bool
|
||||
void
|
||||
RPCChannel::SpinInternalEventLoop()
|
||||
{
|
||||
EnterSpinLoop();
|
||||
|
||||
// Nested windows event loop that's triggered when the child enters into modal
|
||||
// event procedures.
|
||||
// Nested windows event loop we trigger when the child enters into modal
|
||||
// event loops.
|
||||
|
||||
// Note, when we return, we always reset the notify worker event. So there's
|
||||
// no need to reset it on return here.
|
||||
|
||||
do {
|
||||
MSG msg = { 0 };
|
||||
|
||||
@@ -605,33 +606,21 @@ RPCChannel::SpinInternalEventLoop()
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (!Connected()) {
|
||||
ExitSpinLoop();
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!RPCChannel::IsSpinLoopActive()) {
|
||||
ExitSpinLoop();
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// If a modal loop in the child has exited, we want to disable the spin
|
||||
// loop. However, we must continue to wait for a response from the last
|
||||
// rpc call. Returning false here will cause the thread to drop down
|
||||
// into deferred message processing.
|
||||
// If a modal loop in the child has exited, disable spin loop and exit.
|
||||
if (PeekMessageW(&msg, (HWND)-1, gOOPPStopNativeLoopEvent,
|
||||
gOOPPStopNativeLoopEvent, PM_REMOVE)) {
|
||||
DecModalLoopCnt();
|
||||
ExitSpinLoop();
|
||||
return false;
|
||||
}
|
||||
|
||||
// At whatever depth we currently sit, a reply to the rpc call we were
|
||||
// waiting for has been received. Exit out of here and respond to it.
|
||||
// Returning true here causes the WaitForNotify() to return.
|
||||
if (PeekMessageW(&msg, (HWND)-1, gEventLoopMessage, gEventLoopMessage,
|
||||
PM_REMOVE)) {
|
||||
ExitSpinLoop();
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve window or thread messages
|
||||
@@ -639,17 +628,13 @@ RPCChannel::SpinInternalEventLoop()
|
||||
if (msg.message == gOOPPStopNativeLoopEvent) {
|
||||
DecModalLoopCnt();
|
||||
ExitSpinLoop();
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
else if (msg.message == gOOPPSpinNativeLoopEvent) {
|
||||
// Keep the spin loop counter accurate, multiple plugins can show ui.
|
||||
IncModalLoopCnt();
|
||||
continue;
|
||||
}
|
||||
else if (msg.message == gEventLoopMessage) {
|
||||
ExitSpinLoop();
|
||||
return true;
|
||||
}
|
||||
|
||||
// The child UI should have been destroyed before the app is closed, in
|
||||
// which case, we should never get this here.
|
||||
@@ -659,11 +644,22 @@ RPCChannel::SpinInternalEventLoop()
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
ExitSpinLoop();
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Block and wait for any posted application messages
|
||||
WaitMessage();
|
||||
}
|
||||
|
||||
// Note, give dispatching windows events priority over checking if
|
||||
// mEvent is signaled, otherwise heavy ipc traffic can cause jittery
|
||||
// playback of video. We'll exit out on each disaptch above, so ipc
|
||||
// won't get starved.
|
||||
|
||||
// Wait for UI events or a signal from the io thread.
|
||||
DWORD result = MsgWaitForMultipleObjects(1, &mEvent, FALSE, INFINITE,
|
||||
QS_ALLINPUT);
|
||||
if (result == WAIT_OBJECT_0) {
|
||||
// Our NotifyWorkerThread event was signaled
|
||||
ExitSpinLoop();
|
||||
return;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
@@ -723,9 +719,14 @@ SyncChannel::WaitForNotify()
|
||||
// will implicitly have their message queues attached if they are parented
|
||||
// to one another. This wait call, then, will return for a message
|
||||
// delivered to *either* thread.
|
||||
DWORD result = MsgWaitForMultipleObjects(0, NULL, FALSE, INFINITE,
|
||||
DWORD result = MsgWaitForMultipleObjects(1, &mEvent, FALSE, INFINITE,
|
||||
QS_ALLINPUT);
|
||||
if (result != WAIT_OBJECT_0) {
|
||||
if (result == WAIT_OBJECT_0) {
|
||||
// Our NotifyWorkerThread event was signaled
|
||||
ResetEvent(mEvent);
|
||||
break;
|
||||
} else
|
||||
if (result != (WAIT_OBJECT_0 + 1)) {
|
||||
NS_ERROR("Wait failed!");
|
||||
break;
|
||||
}
|
||||
@@ -752,13 +753,6 @@ SyncChannel::WaitForNotify()
|
||||
// above. In that case this PeekMessage call won't actually cause any
|
||||
// mozilla code (or plugin code) to run.
|
||||
|
||||
// We check first to see if we should break out of the loop by looking for
|
||||
// the special message from the IO thread. We pull it out of the queue.
|
||||
if (PeekMessageW(&msg, (HWND)-1, gEventLoopMessage, gEventLoopMessage,
|
||||
PM_REMOVE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// If the following PeekMessage call fails to return a message for us (and
|
||||
// returns false) and we didn't run any "nonqueued" messages then we must
|
||||
// have woken up for a message designated for a window in another thread.
|
||||
@@ -819,7 +813,8 @@ RPCChannel::WaitForNotify()
|
||||
|
||||
if (WaitNeedsSpinLoop()) {
|
||||
SpinInternalEventLoop();
|
||||
return true; // bug 545338
|
||||
ResetEvent(mEvent);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (++gEventLoopDepth == 1) {
|
||||
@@ -860,9 +855,14 @@ RPCChannel::WaitForNotify()
|
||||
}
|
||||
}
|
||||
|
||||
DWORD result = MsgWaitForMultipleObjects(0, NULL, FALSE, INFINITE,
|
||||
DWORD result = MsgWaitForMultipleObjects(1, &mEvent, FALSE, INFINITE,
|
||||
QS_ALLINPUT);
|
||||
if (result != WAIT_OBJECT_0) {
|
||||
if (result == WAIT_OBJECT_0) {
|
||||
// Our NotifyWorkerThread event was signaled
|
||||
ResetEvent(mEvent);
|
||||
break;
|
||||
} else
|
||||
if (result != (WAIT_OBJECT_0 + 1)) {
|
||||
NS_ERROR("Wait failed!");
|
||||
break;
|
||||
}
|
||||
@@ -907,12 +907,11 @@ RPCChannel::WaitForNotify()
|
||||
ScheduleDeferredMessageRun();
|
||||
|
||||
// Spin the internal dispatch message loop during calls to WaitForNotify
|
||||
// until the child process tells us the modal loop has closed. A return
|
||||
// of true indicates gEventLoopMessage was received, exit out of
|
||||
// WaitForNotify so we can deal with it in RPCChannel.
|
||||
// until the child process tells us the modal loop has closed.
|
||||
IncModalLoopCnt();
|
||||
SpinInternalEventLoop();
|
||||
return true; // bug 545338
|
||||
ResetEvent(mEvent);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If a modal loop in the child has exited, we want to disable the spin
|
||||
@@ -923,11 +922,6 @@ RPCChannel::WaitForNotify()
|
||||
break;
|
||||
}
|
||||
|
||||
if (PeekMessageW(&msg, (HWND)-1, gEventLoopMessage, gEventLoopMessage,
|
||||
PM_REMOVE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE) &&
|
||||
!haveSentMessagesPending) {
|
||||
// Message was for child, we should wait a bit.
|
||||
@@ -968,9 +962,9 @@ void
|
||||
SyncChannel::NotifyWorkerThread()
|
||||
{
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
NS_ASSERTION(gUIThreadId, "This should have been set already!");
|
||||
if (!PostThreadMessage(gUIThreadId, gEventLoopMessage, 0, 0)) {
|
||||
NS_WARNING("Failed to post thread message!");
|
||||
NS_ASSERTION(mEvent, "No signal event to set, this is really bad!");
|
||||
if (!SetEvent(mEvent)) {
|
||||
NS_WARNING("Failed to set NotifyWorkerThread event!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user