Remove racy ImageBridgeChild shutdown/creation checks. (bug 1298938 part 4, r=nical)

--HG--
extra : rebase_source : 47d1a0b3da521d81da9ffea7e259104b508b7415
This commit is contained in:
David Anderson 2016-09-08 11:29:31 -07:00
parent 435ec16468
commit 91559fcffe
5 changed files with 61 additions and 78 deletions

View File

@ -147,10 +147,9 @@ OffscreenCanvas::GetContext(JSContext* aCx,
mCanvasRenderer->mGLContext = gl;
mCanvasRenderer->SetIsAlphaPremultiplied(webGL->IsPremultAlpha() || !gl->Caps().alpha);
if (ImageBridgeChild::IsCreated()) {
if (RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton()) {
TextureFlags flags = TextureFlags::ORIGIN_BOTTOM_LEFT;
mCanvasClient = ImageBridgeChild::GetSingleton()->
CreateCanvasClient(CanvasClient::CanvasClientTypeShSurf, flags);
mCanvasClient = imageBridge->CreateCanvasClient(CanvasClient::CanvasClientTypeShSurf, flags);
mCanvasRenderer->SetCanvasClient(mCanvasClient);
gl::GLScreenBuffer* screen = gl->Screen();

View File

@ -42,7 +42,8 @@ MediaSystemResourceManager::Shutdown()
/* static */ void
MediaSystemResourceManager::Init()
{
if (!ImageBridgeChild::IsCreated()) {
RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
if (!imageBridge) {
NS_WARNING("ImageBridge does not exist");
return;
}
@ -73,7 +74,7 @@ MediaSystemResourceManager::Init()
barrier.NotifyAll();
});
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(runnable.forget());
imageBridge->GetMessageLoop()->PostTask(runnable.forget());
// should stop the thread until done.
while (!done) {

View File

@ -151,7 +151,7 @@ GPUProcessManager::EnsureGPUReady()
void
GPUProcessManager::EnsureImageBridgeChild()
{
if (ImageBridgeChild::IsCreated()) {
if (ImageBridgeChild::GetSingleton()) {
return;
}

View File

@ -168,9 +168,6 @@ struct AutoEndTransaction {
CompositableTransaction* mTxn;
};
/* static */
Atomic<bool> ImageBridgeChild::sIsShutDown(false);
void
ImageBridgeChild::UseTextures(CompositableClient* aCompositable,
const nsTArray<TimedTextureClient>& aTextures)
@ -500,6 +497,12 @@ ImageBridgeChild::ShutdownStep2(SynchronousTask* aTask)
Close();
}
void
ImageBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
{
mCanSend = false;
}
void
ImageBridgeChild::CreateImageClientSync(SynchronousTask* aTask,
RefPtr<ImageClient>* result,
@ -523,7 +526,7 @@ ImageBridgeChild::CreateCanvasClientSync(SynchronousTask* aTask,
}
ImageBridgeChild::ImageBridgeChild()
: mShuttingDown(false)
: mCanSend(false)
, mFwdTransactionId(0)
#ifdef MOZ_WIDGET_GONK
, mWaitingFenceHandleMutex("ImageBridgeChild::mWaitingFenceHandleMutex")
@ -547,11 +550,10 @@ ImageBridgeChild::~ImageBridgeChild()
void
ImageBridgeChild::MarkShutDown()
{
MOZ_ASSERT(!mShuttingDown);
mTexturesWaitingRecycled.Clear();
mTrackersHolder.DestroyAsyncTransactionTrackersHolder();
mShuttingDown = true;
mCanSend = false;
}
void
@ -559,8 +561,8 @@ ImageBridgeChild::Connect(CompositableClient* aCompositable,
ImageContainer* aImageContainer)
{
MOZ_ASSERT(aCompositable);
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(InImageBridgeChildThread());
MOZ_ASSERT(CanSend());
uint64_t id = 0;
@ -579,7 +581,7 @@ PCompositableChild*
ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo,
PImageContainerChild* aChild, uint64_t* aID)
{
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(CanSend());
return AsyncCompositableChild::CreateActor();
}
@ -601,11 +603,6 @@ ImageBridgeChild* ImageBridgeChild::GetSingleton()
return sImageBridgeChildSingleton;
}
bool ImageBridgeChild::IsCreated()
{
return GetSingleton() != nullptr;
}
void
ImageBridgeChild::ReleaseImageContainer(RefPtr<ImageContainerChild> aChild)
{
@ -661,12 +658,7 @@ ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient)
void
ImageBridgeChild::UpdateImageClient(RefPtr<ImageClient> aClient, RefPtr<ImageContainer> aContainer)
{
if (!ImageBridgeChild::IsCreated() || ImageBridgeChild::IsShutDown()) {
NS_WARNING("Something is holding on to graphics resources after the shutdown"
"of the graphics subsystem!");
return;
}
if (!aClient || !aContainer || !IsCreated()) {
if (!aClient || !aContainer) {
return;
}
@ -680,6 +672,10 @@ ImageBridgeChild::UpdateImageClient(RefPtr<ImageClient> aClient, RefPtr<ImageCon
return;
}
if (!CanSend()) {
return;
}
// If the client has become disconnected before this event was dispatched,
// early return now.
if (!aClient->IsConnected()) {
@ -725,6 +721,11 @@ void
ImageBridgeChild::UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aWrapper)
{
MOZ_ASSERT(aWrapper);
if (!CanSend()) {
return;
}
BeginTransaction();
aWrapper->GetCanvasClient()->Updated();
EndTransaction();
@ -744,14 +745,7 @@ ImageBridgeChild::FlushAllImagesSync(SynchronousTask* aTask,
AutoCompleteTask complete(aTask);
if (!ImageBridgeChild::IsCreated() || ImageBridgeChild::IsShutDown()) {
// How sad. If we get into this branch it means that the ImageBridge
// got destroyed between the time we ImageBridgeChild::FlushAllImage
// was called on some thread, and the time this function was proxied
// to the ImageBridge thread. ImageBridge gets destroyed way to late
// in the shutdown of gecko for this to be happening for a good reason.
NS_WARNING("Something is holding on to graphics resources after the shutdown"
"of the graphics subsystem!");
if (!CanSend()) {
#ifdef MOZ_WIDGET_GONK
aWaiter->DecrementWaitCount();
#endif
@ -777,12 +771,9 @@ ImageBridgeChild::FlushAllImagesSync(SynchronousTask* aTask,
void
ImageBridgeChild::FlushAllImages(ImageClient* aClient, ImageContainer* aContainer)
{
if (!IsCreated() || IsShutDown()) {
return;
}
MOZ_ASSERT(aClient);
MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
MOZ_ASSERT(!InImageBridgeChildThread());
if (InImageBridgeChildThread()) {
NS_ERROR("ImageBridgeChild::FlushAllImages() is called on ImageBridge thread.");
return;
@ -817,7 +808,7 @@ ImageBridgeChild::FlushAllImages(ImageClient* aClient, ImageContainer* aContaine
void
ImageBridgeChild::BeginTransaction()
{
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(CanSend());
MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
UpdateFwdTransactionId();
mTxn->Begin();
@ -826,7 +817,7 @@ ImageBridgeChild::BeginTransaction()
void
ImageBridgeChild::EndTransaction()
{
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(CanSend());
MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
AutoEndTransaction _(mTxn);
@ -907,6 +898,8 @@ ImageBridgeChild::Bind(Endpoint<PImageBridgeChild>&& aEndpoint)
return;
}
mCanSend = true;
SendImageBridgeThreadId();
}
@ -917,6 +910,8 @@ ImageBridgeChild::BindSameProcess(RefPtr<ImageBridgeParent> aParent)
ipc::MessageChannel *parentChannel = aParent->GetIPCChannel();
Open(parentChannel, parentMsgLoop, mozilla::ipc::ChildSide);
mCanSend = true;
SendImageBridgeThreadId();
}
@ -924,8 +919,6 @@ void ImageBridgeChild::ShutDown()
{
MOZ_ASSERT(NS_IsMainThread());
sIsShutDown = true;
if (RefPtr<ImageBridgeChild> child = GetSingleton()) {
child->WillShutdown();
@ -939,8 +932,6 @@ void ImageBridgeChild::ShutDown()
void
ImageBridgeChild::WillShutdown()
{
MOZ_ASSERT(!mShuttingDown);
{
SynchronousTask task("ImageBridge ShutdownStep1 lock");
@ -1017,7 +1008,7 @@ ImageBridgeChild::InitWithGPUProcess(Endpoint<PImageBridgeChild>&& aEndpoint)
bool InImageBridgeChildThread()
{
return ImageBridgeChild::IsCreated() &&
return sImageBridgeChildThread &&
sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId();
}
@ -1067,7 +1058,6 @@ ImageBridgeChild::CreateImageClientNow(CompositableType aType,
ImageContainer* aImageContainer,
ImageContainerChild* aContainerChild)
{
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(InImageBridgeChildThread());
if (aImageContainer) {
@ -1127,12 +1117,12 @@ ImageBridgeChild::AllocUnsafeShmem(size_t aSize,
ipc::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aShmem)
{
MOZ_ASSERT(!mShuttingDown);
if (InImageBridgeChildThread()) {
return PImageBridgeChild::AllocUnsafeShmem(aSize, aType, aShmem);
} else {
if (!InImageBridgeChildThread()) {
return DispatchAllocShmemInternal(aSize, aType, aShmem, true); // true: unsafe
}
MOZ_ASSERT(CanSend());
return PImageBridgeChild::AllocUnsafeShmem(aSize, aType, aShmem);
}
bool
@ -1140,13 +1130,12 @@ ImageBridgeChild::AllocShmem(size_t aSize,
ipc::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aShmem)
{
MOZ_ASSERT(!mShuttingDown);
if (InImageBridgeChildThread()) {
return PImageBridgeChild::AllocShmem(aSize, aType,
aShmem);
} else {
if (!InImageBridgeChildThread()) {
return DispatchAllocShmemInternal(aSize, aType, aShmem, false); // false: unsafe
}
MOZ_ASSERT(CanSend());
return PImageBridgeChild::AllocShmem(aSize, aType, aShmem);
}
// NewRunnableFunction accepts a limited number of parameters so we need a
@ -1242,7 +1231,7 @@ ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
const TextureFlags&,
const uint64_t& aSerial)
{
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(CanSend());
return TextureClient::CreateIPDLActor();
}
@ -1255,7 +1244,7 @@ ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
PMediaSystemResourceManagerChild*
ImageBridgeChild::AllocPMediaSystemResourceManagerChild()
{
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(CanSend());
return new mozilla::media::MediaSystemResourceManagerChild();
}
@ -1355,7 +1344,7 @@ ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
TextureFlags aFlags,
uint64_t aSerial)
{
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(CanSend());
return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial);
}
@ -1392,7 +1381,7 @@ void
ImageBridgeChild::RemoveTextureFromCompositable(CompositableClient* aCompositable,
TextureClient* aTexture)
{
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(CanSend());
MOZ_ASSERT(aTexture);
MOZ_ASSERT(aTexture->IsSharedWithCompositor());
MOZ_ASSERT(aCompositable->IsConnected());
@ -1416,7 +1405,7 @@ ImageBridgeChild::RemoveTextureFromCompositableAsync(AsyncTransactionTracker* aA
CompositableClient* aCompositable,
TextureClient* aTexture)
{
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(CanSend());
MOZ_ASSERT(aTexture);
MOZ_ASSERT(aTexture->IsSharedWithCompositor());
MOZ_ASSERT(aCompositable->IsConnected());
@ -1456,6 +1445,13 @@ ImageBridgeChild::Destroy(CompositableChild* aCompositable)
CompositableForwarder::Destroy(aCompositable);
}
bool
ImageBridgeChild::CanSend() const
{
MOZ_ASSERT(InImageBridgeChildThread());
return mCanSend;
}
void
ImageBridgeChild::OnXPCOMShutdown()
{
@ -1491,6 +1487,5 @@ ImageBridgeChild::ShutdownObserver::Observe(nsISupports* aSubject,
return NS_OK;
}
} // namespace layers
} // namespace mozilla

View File

@ -138,22 +138,6 @@ public:
*/
static void ShutDown();
/**
* Returns true if the singleton has been created.
*
* Can be called from any thread.
*/
static bool IsCreated();
/**
* Returns true if the singleton's ShutDown() was called.
*
* Can be called from any thread.
*/
static bool IsShutDown()
{
return sIsShutDown;
}
/**
* returns the singleton instance.
*
@ -401,6 +385,10 @@ protected:
void MarkShutDown();
void FallbackDestroyActors();
void ActorDestroy(ActorDestroyReason aWhy) override;
bool CanSend() const;
private:
class ShutdownObserver final : public nsIObserver
{
@ -422,8 +410,8 @@ private:
private:
CompositableTransaction* mTxn;
Atomic<bool> mShuttingDown;
static Atomic<bool> sIsShutDown;
bool mCanSend;
/**
* Transaction id of CompositableForwarder.