mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 20:35:50 +00:00
Bug 1366011 - IPCBlob should not have race conditions between Send__delete__ and RecvStreamNeeded, r=smaug
This commit is contained in:
parent
576157499c
commit
318848612a
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -56,6 +56,9 @@ public:
|
||||
mozilla::ipc::IPCResult
|
||||
RecvStreamReady(const OptionalIPCStream& aStream) override;
|
||||
|
||||
void
|
||||
Shutdown();
|
||||
|
||||
private:
|
||||
~IPCBlobInputStreamChild();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -20,11 +20,11 @@ protocol PIPCBlobInputStream
|
||||
|
||||
parent:
|
||||
async StreamNeeded();
|
||||
|
||||
async __delete__();
|
||||
async Close();
|
||||
|
||||
child:
|
||||
async StreamReady(OptionalIPCStream aStream);
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
Loading…
Reference in New Issue
Block a user