Bug 1224825 - Race condition in MessagePort::close, r=smaug

This commit is contained in:
Andrea Marchesini
2015-11-15 11:46:53 +00:00
parent e625ba38f2
commit c65553ebc9
5 changed files with 153 additions and 10 deletions

View File

@@ -36,6 +36,9 @@ public:
: mDestinationUUID(aDestinationUUID)
, mSequenceID(1)
, mParent(nullptr)
// By default we don't know the next parent.
, mWaitingForNewParent(true)
, mNextStepCloseAll(false)
{
MOZ_COUNT_CTOR(MessagePortServiceData);
}
@@ -62,6 +65,9 @@ public:
FallibleTArray<NextParent> mNextParents;
FallibleTArray<RefPtr<SharedMessagePortMessage>> mMessages;
bool mWaitingForNewParent;
bool mNextStepCloseAll;
};
/* static */ MessagePortService*
@@ -113,31 +119,49 @@ MessagePortService::RequestEntangling(MessagePortParent* aParent,
// This is a security check.
if (!data->mDestinationUUID.Equals(aDestinationUUID)) {
MOZ_ASSERT(false, "DestinationUUIDs do not match!");
CloseAll(aParent->ID());
return false;
}
if (aSequenceID < data->mSequenceID) {
MOZ_ASSERT(false, "Invalid sequence ID!");
CloseAll(aParent->ID());
return false;
}
if (aSequenceID == data->mSequenceID) {
if (data->mParent) {
MOZ_ASSERT(false, "Two ports cannot have the same sequenceID.");
CloseAll(aParent->ID());
return false;
}
// We activate this port, sending all the messages.
data->mParent = aParent;
data->mWaitingForNewParent = false;
FallibleTArray<MessagePortMessage> array;
if (!SharedMessagePortMessage::FromSharedToMessagesParent(aParent,
data->mMessages,
array)) {
CloseAll(aParent->ID());
return false;
}
data->mMessages.Clear();
return aParent->Entangled(array);
// We can entangle the port.
if (!aParent->Entangled(array)) {
CloseAll(aParent->ID());
return false;
}
// If we were waiting for this parent in order to close this channel, this
// is the time to do it.
if (data->mNextStepCloseAll) {
CloseAll(aParent->ID());
}
return true;
}
// This new parent will be the next one when a Disentangle request is
@@ -145,6 +169,7 @@ MessagePortService::RequestEntangling(MessagePortParent* aParent,
MessagePortServiceData::NextParent* nextParent =
data->mNextParents.AppendElement(mozilla::fallible);
if (!nextParent) {
CloseAll(aParent->ID());
return false;
}
@@ -193,6 +218,7 @@ MessagePortService::DisentanglePort(
// We didn't find the parent.
if (!nextParent) {
data->mMessages.SwapElements(aMessages);
data->mWaitingForNewParent = true;
data->mParent = nullptr;
return true;
}
@@ -267,6 +293,20 @@ MessagePortService::CloseAll(const nsID& aUUID)
}
nsID destinationUUID = data->mDestinationUUID;
// If we have informations about the other port and that port has some
// pending messages to deliver but the parent has not processed them yet,
// because its entangling request didn't arrive yet), we cannot close this
// channel.
MessagePortServiceData* destinationData;
if (mPorts.Get(destinationUUID, &destinationData) &&
!destinationData->mMessages.IsEmpty() &&
destinationData->mWaitingForNewParent) {
MOZ_ASSERT(!destinationData->mNextStepCloseAll);
destinationData->mNextStepCloseAll = true;
return;
}
mPorts.Remove(aUUID);
CloseAll(destinationUUID);