Bug 877534 - Use a shutdown listener to destroy the compositor from nsBaseWidget. r=roc

This prevents a case where the nsBaseWidget isn't destroyed until the cycle collector is shutdown,
and we are too late in the shutdown sequence to process the events that get queued during
Compositor teardown.
This commit is contained in:
Matt Woodrow 2013-06-17 14:50:32 +12:00
Родитель 50e4cfb594
Коммит 614a80c1a6
3 изменённых файлов: 54 добавлений и 1 удалений

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

@ -555,7 +555,7 @@ private:
gfx::IntSize mSize;
GLuint mTextureHandle;
GLenum mGLFormat;
gl::GLContext* mGL;
nsRefPtr<gl::GLContext> mGL;
};
#ifdef MOZ_WIDGET_GONK

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

@ -118,8 +118,31 @@ nsBaseWidget::nsBaseWidget()
#ifdef DEBUG
debug_RegisterPrefCallbacks();
#endif
mShutdownObserver = new WidgetShutdownObserver(this);
nsContentUtils::RegisterShutdownObserver(mShutdownObserver);
}
NS_IMPL_ISUPPORTS1(WidgetShutdownObserver, nsIObserver)
NS_IMETHODIMP
WidgetShutdownObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
mWidget->Shutdown();
nsContentUtils::UnregisterShutdownObserver(this);
}
return NS_OK;
}
void
nsBaseWidget::Shutdown()
{
DestroyCompositor();
mShutdownObserver = nullptr;
}
static void DeferredDestroyCompositor(CompositorParent* aCompositorParent,
CompositorChild* aCompositorChild)
@ -171,6 +194,10 @@ nsBaseWidget::~nsBaseWidget()
mLayerManager = nullptr;
}
if (mShutdownObserver) {
nsContentUtils::UnregisterShutdownObserver(mShutdownObserver);
}
DestroyCompositor();
#ifdef NOISY_WIDGET_LEAKS
@ -893,6 +920,12 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
// Recreating this is tricky, as we may still have an old and we need
// to make sure it's properly destroyed by calling DestroyCompositor!
// If we've already received a shutdown notification, don't try
// create a new compositor.
if (!mShutdownObserver) {
return;
}
mCompositorParent = NewCompositorParent(aWidth, aHeight);
AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel();
LayerManager* lm = new ClientLayerManager(this);

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

@ -15,6 +15,7 @@
#include "nsGUIEvent.h"
#include "nsAutoPtr.h"
#include "nsIRollupListener.h"
#include "nsIObserver.h"
#include <algorithm>
class nsIContent;
class nsAutoRollup;
@ -38,6 +39,22 @@ namespace base {
class Thread;
}
class nsBaseWidget;
class WidgetShutdownObserver MOZ_FINAL : public nsIObserver
{
public:
WidgetShutdownObserver(nsBaseWidget* aWidget)
: mWidget(aWidget)
{ }
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
private:
nsBaseWidget *mWidget;
};
/**
* Common widget implementation used as base class for native
* or crossplatform implementations of Widgets.
@ -254,6 +271,8 @@ public:
static nsIRollupListener* GetActiveRollupListener();
void Shutdown();
protected:
virtual void ResolveIconName(const nsAString &aIconName,
@ -356,6 +375,7 @@ protected:
nsRefPtr<LayerManager> mBasicLayerManager;
nsRefPtr<CompositorChild> mCompositorChild;
nsRefPtr<CompositorParent> mCompositorParent;
nsCOMPtr<WidgetShutdownObserver> mShutdownObserver;
nscolor mBackground;
nscolor mForeground;
nsCursor mCursor;