mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1153939 - Avoid a race condition with setting nsBaseWidgets WidgetShutdownObserver widget pointer to null. Fixes a crash in nsBaseWidget::DestroyCompositor(). r=roc
--HG-- extra : rebase_source : 3b38830b93428aedc44c83278efe4667f77fd0ba
This commit is contained in:
parent
39caf57915
commit
27569381f4
@ -154,35 +154,65 @@ nsBaseWidget::nsBaseWidget()
|
||||
}
|
||||
#endif
|
||||
mShutdownObserver = new WidgetShutdownObserver(this);
|
||||
nsContentUtils::RegisterShutdownObserver(mShutdownObserver);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(WidgetShutdownObserver, nsIObserver)
|
||||
|
||||
WidgetShutdownObserver::WidgetShutdownObserver(nsBaseWidget* aWidget) :
|
||||
mWidget(aWidget),
|
||||
mRegistered(false)
|
||||
{
|
||||
Register();
|
||||
}
|
||||
|
||||
WidgetShutdownObserver::~WidgetShutdownObserver()
|
||||
{
|
||||
// No need to call Unregister(), we can't be destroyed until nsBaseWidget
|
||||
// gets torn down. The observer service and nsBaseWidget have a ref on us
|
||||
// so nsBaseWidget has to call Unregister and then clear its ref.
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WidgetShutdownObserver::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
const char16_t *aData)
|
||||
{
|
||||
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0 &&
|
||||
mWidget) {
|
||||
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
||||
if (sPluginWidgetList) {
|
||||
delete sPluginWidgetList;
|
||||
sPluginWidgetList = nullptr;
|
||||
}
|
||||
#endif
|
||||
if (mWidget && !strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip(mWidget);
|
||||
mWidget->Shutdown();
|
||||
nsContentUtils::UnregisterShutdownObserver(this);
|
||||
}
|
||||
return NS_OK;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
WidgetShutdownObserver::Register()
|
||||
{
|
||||
if (!mRegistered) {
|
||||
mRegistered = true;
|
||||
nsContentUtils::RegisterShutdownObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WidgetShutdownObserver::Unregister()
|
||||
{
|
||||
if (mRegistered) {
|
||||
nsContentUtils::UnregisterShutdownObserver(this);
|
||||
mRegistered = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBaseWidget::Shutdown()
|
||||
{
|
||||
DestroyCompositor();
|
||||
mShutdownObserver = nullptr;
|
||||
FreeShutdownObserver();
|
||||
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
||||
if (sPluginWidgetList) {
|
||||
delete sPluginWidgetList;
|
||||
sPluginWidgetList = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void nsBaseWidget::DestroyCompositor()
|
||||
@ -205,6 +235,15 @@ void nsBaseWidget::DestroyLayerManager()
|
||||
DestroyCompositor();
|
||||
}
|
||||
|
||||
void
|
||||
nsBaseWidget::FreeShutdownObserver()
|
||||
{
|
||||
if (mShutdownObserver) {
|
||||
mShutdownObserver->Unregister();
|
||||
}
|
||||
mShutdownObserver = nullptr;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsBaseWidget destructor
|
||||
@ -217,15 +256,7 @@ nsBaseWidget::~nsBaseWidget()
|
||||
static_cast<BasicLayerManager*>(mLayerManager.get())->ClearRetainerWidget();
|
||||
}
|
||||
|
||||
if (mShutdownObserver) {
|
||||
// If the shutdown observer is currently processing observers,
|
||||
// then UnregisterShutdownObserver won't stop our Observer
|
||||
// function from being called. Make sure we don't try
|
||||
// to reference the dead widget.
|
||||
mShutdownObserver->mWidget = nullptr;
|
||||
nsContentUtils::UnregisterShutdownObserver(mShutdownObserver);
|
||||
}
|
||||
|
||||
FreeShutdownObserver();
|
||||
DestroyLayerManager();
|
||||
|
||||
#ifdef NOISY_WIDGET_LEAKS
|
||||
|
@ -56,19 +56,22 @@ class Thread;
|
||||
|
||||
class nsBaseWidget;
|
||||
|
||||
// Helper class used in shutting down gfx related code.
|
||||
class WidgetShutdownObserver final : public nsIObserver
|
||||
{
|
||||
~WidgetShutdownObserver() {}
|
||||
~WidgetShutdownObserver();
|
||||
|
||||
public:
|
||||
explicit WidgetShutdownObserver(nsBaseWidget* aWidget)
|
||||
: mWidget(aWidget)
|
||||
{ }
|
||||
explicit WidgetShutdownObserver(nsBaseWidget* aWidget);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
void Register();
|
||||
void Unregister();
|
||||
|
||||
nsBaseWidget *mWidget;
|
||||
bool mRegistered;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -471,6 +474,8 @@ protected:
|
||||
void DestroyCompositor();
|
||||
void DestroyLayerManager();
|
||||
|
||||
void FreeShutdownObserver();
|
||||
|
||||
nsIWidgetListener* mWidgetListener;
|
||||
nsIWidgetListener* mAttachedWidgetListener;
|
||||
nsRefPtr<LayerManager> mLayerManager;
|
||||
|
Loading…
Reference in New Issue
Block a user