Bug 1392705 - part 3: Call nsBaseWidget::DestroyLayerManager() in nsWindow::Destroy to ensure IPC is not shutdown in the destructor for Android r=jchen
Due to the indeterminate nature of Gecko shutdown, the ref count of the
nsWindow on Android would sometimes go to zero before the XPCOM shutdown
observer was called in nsBaseWindow which is where the compositor thread
IPC is shutdown. If nsBaseWindow::Shutdown does not get called, then the
compositor thread IPC is shutdown in the nsBaseWindow destructor.
Unfortunately while the nsWindow is being deleted, it can be accessed in
the compositor thread and cause a crash in
LayerManagerComposite::RenderToPresentationSurface.
Calling nsBaseWidget::DestroyLayerManager() in nsWindow::Destroy()
ensures it gets called before the destructor gets invoked typically in
the Destroy() call.
MozReview-Commit-ID: KCv8SCmEjnb
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -1470,16 +1470,20 @@ nsWindow::nsWindow() :
mIsFullScreen(false)
{
}
nsWindow::~nsWindow()
{
gTopLevelWindows.RemoveElement(this);
ALOG("nsWindow %p destructor", (void*)this);
+ // The mCompositorSession should have been cleaned up in nsWindow::Destroy()
+ // DestroyLayerManager() will call DestroyCompositor() which will crash if
+ // called from nsBaseWidget destructor. See Bug 1392705
+ MOZ_ASSERT(!mCompositorSession);
}
bool
nsWindow::IsTopLevel()
{
return mWindowType == eWindowType_toplevel ||
mWindowType == eWindowType_dialog ||
mWindowType == eWindowType_invisible;
@@ -1541,16 +1545,19 @@ nsWindow::Destroy()
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
while (mChildren.Length()) {
// why do we still have children?
ALOG("### Warning: Destroying window %p and reparenting child %p to null!", (void*)this, (void*)mChildren[0]);
mChildren[0]->SetParent(nullptr);
}
+ // Ensure the compositor has been shutdown before this nsWindow is potentially deleted
+ nsBaseWidget::DestroyCompositor();
+
nsBaseWidget::Destroy();
if (IsTopLevel())
gTopLevelWindows.RemoveElement(this);
SetParent(nullptr);
nsBaseWidget::OnDestroy();