Bug 998863: Asynchronous Plugin Initialization, Part 3: ipc/glue changes; r=dvander
This commit is contained in:
@@ -298,6 +298,7 @@ MessageChannel::MessageChannel(MessageListener *aListener)
|
|||||||
mRecvdErrors(0),
|
mRecvdErrors(0),
|
||||||
mRemoteStackDepthGuess(false),
|
mRemoteStackDepthGuess(false),
|
||||||
mSawInterruptOutMsg(false),
|
mSawInterruptOutMsg(false),
|
||||||
|
mIsWaitingForIncoming(false),
|
||||||
mAbortOnError(false),
|
mAbortOnError(false),
|
||||||
mBlockScripts(false),
|
mBlockScripts(false),
|
||||||
mFlags(REQUIRE_DEFAULT),
|
mFlags(REQUIRE_DEFAULT),
|
||||||
@@ -664,7 +665,8 @@ MessageChannel::OnMessageReceivedFromLink(const Message& aMsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool shouldWakeUp = AwaitingInterruptReply() ||
|
bool shouldWakeUp = AwaitingInterruptReply() ||
|
||||||
(AwaitingSyncReply() && !ShouldDeferMessage(aMsg));
|
(AwaitingSyncReply() && !ShouldDeferMessage(aMsg)) ||
|
||||||
|
AwaitingIncomingMessage();
|
||||||
|
|
||||||
// There are three cases we're concerned about, relating to the state of the
|
// There are three cases we're concerned about, relating to the state of the
|
||||||
// main thread:
|
// main thread:
|
||||||
@@ -987,6 +989,35 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MessageChannel::WaitForIncomingMessage()
|
||||||
|
{
|
||||||
|
#ifdef OS_WIN
|
||||||
|
SyncStackFrame frame(this, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ // Scope for lock
|
||||||
|
MonitorAutoLock lock(*mMonitor);
|
||||||
|
AutoEnterWaitForIncoming waitingForIncoming(*this);
|
||||||
|
if (mChannelState != ChannelConnected) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!HasPendingEvents()) {
|
||||||
|
return WaitForInterruptNotify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OnMaybeDequeueOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MessageChannel::HasPendingEvents()
|
||||||
|
{
|
||||||
|
AssertWorkerThread();
|
||||||
|
mMonitor->AssertCurrentThreadOwns();
|
||||||
|
return Connected() && !mPending.empty();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MessageChannel::InterruptEventOccurred()
|
MessageChannel::InterruptEventOccurred()
|
||||||
{
|
{
|
||||||
@@ -1546,7 +1577,7 @@ MessageChannel::OnChannelErrorFromLink()
|
|||||||
if (InterruptStackDepth() > 0)
|
if (InterruptStackDepth() > 0)
|
||||||
NotifyWorkerThread();
|
NotifyWorkerThread();
|
||||||
|
|
||||||
if (AwaitingSyncReply())
|
if (AwaitingSyncReply() || AwaitingIncomingMessage())
|
||||||
NotifyWorkerThread();
|
NotifyWorkerThread();
|
||||||
|
|
||||||
if (ChannelClosing != mChannelState) {
|
if (ChannelClosing != mChannelState) {
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ class MessageChannel : HasResultCodes
|
|||||||
// Make an Interrupt call to the other side of the channel
|
// Make an Interrupt call to the other side of the channel
|
||||||
bool Call(Message* aMsg, Message* aReply);
|
bool Call(Message* aMsg, Message* aReply);
|
||||||
|
|
||||||
|
// Wait until a message is received
|
||||||
|
bool WaitForIncomingMessage();
|
||||||
|
|
||||||
bool CanSend() const;
|
bool CanSend() const;
|
||||||
|
|
||||||
void SetReplyTimeoutMs(int32_t aTimeoutMs);
|
void SetReplyTimeoutMs(int32_t aTimeoutMs);
|
||||||
@@ -214,6 +217,7 @@ class MessageChannel : HasResultCodes
|
|||||||
void DispatchOnChannelConnected();
|
void DispatchOnChannelConnected();
|
||||||
|
|
||||||
bool InterruptEventOccurred();
|
bool InterruptEventOccurred();
|
||||||
|
bool HasPendingEvents();
|
||||||
|
|
||||||
bool ProcessPendingRequest(const Message &aUrgent);
|
bool ProcessPendingRequest(const Message &aUrgent);
|
||||||
|
|
||||||
@@ -319,6 +323,30 @@ class MessageChannel : HasResultCodes
|
|||||||
mMonitor->AssertCurrentThreadOwns();
|
mMonitor->AssertCurrentThreadOwns();
|
||||||
return !mInterruptStack.empty();
|
return !mInterruptStack.empty();
|
||||||
}
|
}
|
||||||
|
bool AwaitingIncomingMessage() const {
|
||||||
|
mMonitor->AssertCurrentThreadOwns();
|
||||||
|
return mIsWaitingForIncoming;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MOZ_STACK_CLASS AutoEnterWaitForIncoming
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit AutoEnterWaitForIncoming(MessageChannel& aChannel)
|
||||||
|
: mChannel(aChannel)
|
||||||
|
{
|
||||||
|
aChannel.mMonitor->AssertCurrentThreadOwns();
|
||||||
|
aChannel.mIsWaitingForIncoming = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~AutoEnterWaitForIncoming()
|
||||||
|
{
|
||||||
|
mChannel.mIsWaitingForIncoming = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MessageChannel& mChannel;
|
||||||
|
};
|
||||||
|
friend class AutoEnterWaitForIncoming;
|
||||||
|
|
||||||
// Returns true if we're dispatching a sync message's callback.
|
// Returns true if we're dispatching a sync message's callback.
|
||||||
bool DispatchingSyncMessage() const {
|
bool DispatchingSyncMessage() const {
|
||||||
@@ -639,6 +667,11 @@ class MessageChannel : HasResultCodes
|
|||||||
// ExitedCxxStack(), from which this variable is reset.
|
// ExitedCxxStack(), from which this variable is reset.
|
||||||
bool mSawInterruptOutMsg;
|
bool mSawInterruptOutMsg;
|
||||||
|
|
||||||
|
// Are we waiting on this channel for an incoming message? This is used
|
||||||
|
// to implement WaitForIncomingMessage(). Must only be accessed while owning
|
||||||
|
// mMonitor.
|
||||||
|
bool mIsWaitingForIncoming;
|
||||||
|
|
||||||
// Map of replies received "out of turn", because of Interrupt
|
// Map of replies received "out of turn", because of Interrupt
|
||||||
// in-calls racing with replies to outstanding in-calls. See
|
// in-calls racing with replies to outstanding in-calls. See
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=521929.
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=521929.
|
||||||
|
|||||||
@@ -966,7 +966,7 @@ MessageChannel::WaitForInterruptNotify()
|
|||||||
return WaitForSyncNotify();
|
return WaitForSyncNotify();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InterruptStackDepth()) {
|
if (!InterruptStackDepth() && !AwaitingIncomingMessage()) {
|
||||||
// There is currently no way to recover from this condition.
|
// There is currently no way to recover from this condition.
|
||||||
NS_RUNTIMEABORT("StackDepth() is 0 in call to MessageChannel::WaitForNotify!");
|
NS_RUNTIMEABORT("StackDepth() is 0 in call to MessageChannel::WaitForNotify!");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user