Bug 1540733 - Create a new IPCBlobInputStreamChild actor when migrating, r=baku

Differential Revision: https://phabricator.services.mozilla.com/D27970

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nika Layzell 2019-04-18 15:23:54 +00:00
Родитель e12dc53ba3
Коммит d4f1348c4b
7 изменённых файлов: 49 добавлений и 22 удалений

Просмотреть файл

@ -915,5 +915,12 @@ void IPCBlobInputStream::LengthReady(int64_t aLength) {
}
}
void IPCBlobInputStream::ActorMigrated(IPCBlobInputStreamChild* aNewActor) {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mActor->Size() == aNewActor->Size());
MOZ_ASSERT(mActor->ID() == aNewActor->ID());
mActor = aNewActor;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -78,6 +78,8 @@ class IPCBlobInputStream final : public nsIAsyncInputStream,
return nullptr;
}
void ActorMigrated(IPCBlobInputStreamChild* aNewActor);
private:
~IPCBlobInputStream();

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/dom/WorkerRef.h"
#include "mozilla/ipc/PBackgroundChild.h"
namespace mozilla {
namespace dom {
@ -182,7 +183,6 @@ void IPCBlobInputStreamChild::ActorDestroy(
IPCBlobInputStreamThread::GetOrCreate();
MOZ_ASSERT(thread, "We cannot continue without DOMFile thread.");
ResetManager();
thread->MigrateActor(this);
return;
}
@ -386,14 +386,41 @@ mozilla::ipc::IPCResult IPCBlobInputStreamChild::RecvLengthReady(
return IPC_OK();
}
void IPCBlobInputStreamChild::Migrated() {
void IPCBlobInputStreamChild::MigrateTo(PBackgroundChild* aManager) {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mState == eInactiveMigrating);
mWorkerRef = nullptr;
// Construct the replacement actor, sending the IPC constructor. The reference
// taken will be freed by DeallocPIPCBlobInputStreamConstructor.
RefPtr<IPCBlobInputStreamChild> actor =
new IPCBlobInputStreamChild(mID, mSize);
if (!aManager->SendPIPCBlobInputStreamConstructor(do_AddRef(actor).take(),
mID, mSize)) {
return;
}
actor->MigratedFrom(this);
// Finally, complete teardown of the old actor.
MOZ_ASSERT(mStreams.IsEmpty() && mPendingOperations.IsEmpty());
mWorkerRef = nullptr;
mState = eInactive;
}
void IPCBlobInputStreamChild::MigratedFrom(IPCBlobInputStreamChild* aOldActor) {
MutexAutoLock lock(mMutex);
aOldActor->mMutex.AssertCurrentThreadOwns();
mOwningEventTarget = GetCurrentThreadSerialEventTarget();
MOZ_ASSERT(IPCBlobInputStreamThread::IsOnFileEventTarget(mOwningEventTarget));
MOZ_ASSERT(mState == eActive);
// Take streams & pending operations from |aOldActor|.
mStreams.SwapElements(aOldActor->mStreams);
mPendingOperations.SwapElements(aOldActor->mPendingOperations);
for (auto* stream : mStreams) {
stream->ActorMigrated(this);
}
// Maybe we have no reasons to keep this actor alive.
if (mStreams.IsEmpty()) {
@ -402,8 +429,6 @@ void IPCBlobInputStreamChild::Migrated() {
return;
}
mState = eActive;
// Let's processing the pending operations. We need a stream for each pending
// operation.
for (uint32_t i = 0; i < mPendingOperations.Length(); ++i) {

Просмотреть файл

@ -64,11 +64,13 @@ class IPCBlobInputStreamChild final
void Shutdown();
void Migrated();
void MigrateTo(PBackgroundChild* aManager);
private:
~IPCBlobInputStreamChild();
void MigratedFrom(IPCBlobInputStreamChild* aOldActor);
// Raw pointers because these streams keep this actor alive. When the last
// stream is unregister, the actor will be deleted. This list is protected by
// mutex.

Просмотреть файл

@ -79,7 +79,7 @@ void IPCBlobInputStreamParent::ActorDestroy(
if (mMigrating) {
if (callback && storage) {
// We need to assign this callback to the next parent.
IPCBlobInputStreamStorage::Get()->StoreCallback(mID, callback);
storage->StoreCallback(mID, callback);
}
return;
}

Просмотреть файл

@ -47,23 +47,13 @@ class MigrateActorRunnable final : public Runnable {
NS_IMETHOD
Run() override {
MOZ_ASSERT(mActor->State() == IPCBlobInputStreamChild::eInactiveMigrating);
PBackgroundChild* actorChild =
BackgroundChild::GetOrCreateForCurrentThread();
if (!actorChild) {
return NS_OK;
}
if (actorChild->SendPIPCBlobInputStreamConstructor(mActor, mActor->ID(),
mActor->Size())) {
// We need manually to increase the reference for this actor because the
// IPC allocator method is not triggered. The Release() is called by IPDL
// when the actor is deleted.
mActor.get()->AddRef();
mActor->Migrated();
}
mActor->MigrateTo(actorChild);
return NS_OK;
}

Просмотреть файл

@ -166,9 +166,10 @@
* used to assign IPCBlobInputStreamChild actor to the DOM-File thread.
* IPCBlobInputStreamThread::GetOrCreate() creates the DOM-File thread if it
* doesn't exist yet and it initializes PBackground on it if needed.
* 5. IPCBlobInputStreamChild is reused on the DOM-File thread for the creation
* of a new IPCBlobInputStreamParent actor on the parent side. Doing this,
* IPCBlobInputStreamChild will now be owned by the DOM-File thread.
* 5. A new IPCBlobInputStreamChild is created on the DOM-File thread for the
* creation of a new IPCBlobInputStreamParent actor on the parent side.
* Pending operations and IPCBlobInputStreams are moved onto the new actor,
* and back references are updated.
* 6. When the new IPCBlobInputStreamParent actor is created, it will receive
* the same UUID of the previous parent actor. The nsIInputStream will be
* retrieved from IPCBlobInputStreamStorage.