Bug 1366011 - IPCBlob should not have race conditions between Send__delete__ and RecvStreamNeeded, r=smaug

This commit is contained in:
Andrea Marchesini 2017-05-18 23:06:22 +02:00
parent 576157499c
commit 318848612a
6 changed files with 61 additions and 12 deletions

View File

@ -192,6 +192,10 @@ IPCBlobInputStream::Clone(nsIInputStream** aResult)
MOZ_ASSERT(mActor);
nsCOMPtr<nsIInputStream> stream = mActor->CreateStream();
if (!stream) {
return NS_ERROR_FAILURE;
}
stream.forget(aResult);
return NS_OK;
}

View File

@ -13,19 +13,17 @@ namespace {
// This runnable is used in case the last stream is forgotten on the 'wrong'
// thread.
class DeleteRunnable final : public Runnable
class ShutdownRunnable final : public Runnable
{
public:
explicit DeleteRunnable(IPCBlobInputStreamChild* aActor)
explicit ShutdownRunnable(IPCBlobInputStreamChild* aActor)
: mActor(aActor)
{}
NS_IMETHOD
Run() override
{
if (mActor->IsAlive()) {
mActor->Send__delete__(mActor);
}
mActor->Shutdown();
return NS_OK;
}
@ -96,10 +94,29 @@ IPCBlobInputStreamChild::~IPCBlobInputStreamChild()
{}
void
IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason)
IPCBlobInputStreamChild::Shutdown()
{
MutexAutoLock lock(mMutex);
mActorAlive = false;
RefPtr<IPCBlobInputStreamChild> kungFuDeathGrip = this;
mPendingOperations.Clear();
if (mActorAlive) {
SendClose();
mActorAlive = false;
}
}
void
IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason)
{
{
MutexAutoLock lock(mMutex);
mActorAlive = false;
}
Shutdown();
}
bool
@ -114,6 +131,10 @@ IPCBlobInputStreamChild::CreateStream()
{
MutexAutoLock lock(mMutex);
if (!mActorAlive) {
return nullptr;
}
RefPtr<IPCBlobInputStream> stream = new IPCBlobInputStream(this);
mStreams.AppendElement(stream);
return stream.forget();
@ -124,7 +145,7 @@ IPCBlobInputStreamChild::ForgetStream(IPCBlobInputStream* aStream)
{
MOZ_ASSERT(aStream);
RefPtr<IPCBlobInputStreamChild> kungFoDeathGrip = this;
RefPtr<IPCBlobInputStreamChild> kungFuDeathGrip = this;
{
MutexAutoLock lock(mMutex);
@ -136,11 +157,11 @@ IPCBlobInputStreamChild::ForgetStream(IPCBlobInputStream* aStream)
}
if (mOwningThread == NS_GetCurrentThread()) {
Send__delete__(this);
Shutdown();
return;
}
RefPtr<DeleteRunnable> runnable = new DeleteRunnable(this);
RefPtr<ShutdownRunnable> runnable = new ShutdownRunnable(this);
mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
}
@ -149,6 +170,11 @@ IPCBlobInputStreamChild::StreamNeeded(IPCBlobInputStream* aStream,
nsIEventTarget* aEventTarget)
{
MutexAutoLock lock(mMutex);
if (!mActorAlive) {
return;
}
MOZ_ASSERT(mStreams.Contains(aStream));
PendingOperation* opt = mPendingOperations.AppendElement();
@ -175,6 +201,7 @@ IPCBlobInputStreamChild::RecvStreamReady(const OptionalIPCStream& aStream)
{
MutexAutoLock lock(mMutex);
MOZ_ASSERT(!mPendingOperations.IsEmpty());
MOZ_ASSERT(mActorAlive);
pendingStream = mPendingOperations[0].mStream;
eventTarget = mPendingOperations[0].mEventTarget;

View File

@ -56,6 +56,9 @@ public:
mozilla::ipc::IPCResult
RecvStreamReady(const OptionalIPCStream& aStream) override;
void
Shutdown();
private:
~IPCBlobInputStreamChild();

View File

@ -96,5 +96,17 @@ IPCBlobInputStreamParent::RecvStreamNeeded()
return IPC_OK();
}
mozilla::ipc::IPCResult
IPCBlobInputStreamParent::RecvClose()
{
MOZ_ASSERT(mContentManager || mPBackgroundManager);
if (!Send__delete__(this)) {
return IPC_FAIL(this, "Send__delete_ failed");
}
return IPC_OK();
}
} // namespace dom
} // namespace mozilla

View File

@ -44,6 +44,9 @@ public:
mozilla::ipc::IPCResult
RecvStreamNeeded() override;
mozilla::ipc::IPCResult
RecvClose() override;
private:
IPCBlobInputStreamParent(const nsID& aID, uint64_t aSize,
nsIContentParent* aManager);

View File

@ -20,11 +20,11 @@ protocol PIPCBlobInputStream
parent:
async StreamNeeded();
async __delete__();
async Close();
child:
async StreamReady(OptionalIPCStream aStream);
async __delete__();
};
} // namespace dom