Bug 722012 - Fixes crash on Gtk widget destruction when using OMTC on linux. r=karlt

--HG--
extra : rebase_source : 5562c7e466bd54fecd69e8a9b4c469e24493542f
This commit is contained in:
Nicolas Silva 2012-05-23 10:17:44 -04:00
parent d6e5466d4e
commit ea8d81c8ec
3 changed files with 41 additions and 20 deletions

View File

@ -624,6 +624,13 @@ nsWindow::Destroy(void)
}
mLayerManager = nsnull;
// It is safe to call DestroyeCompositor several times (here and
// in the parent class) since it will take effect only once.
// The reason we call it here is because on gtk platforms we need
// to destroy the compositor before we destroy the gdk window (which
// destroys the the gl context attached to it).
DestroyCompositor();
ClearCachedResources();
g_signal_handlers_disconnect_by_func(gtk_settings_get_default(),

View File

@ -110,7 +110,7 @@ nsBaseWidget::nsBaseWidget()
}
static void DestroyCompositor(CompositorParent* aCompositorParent,
static void DeferredDestroyCompositor(CompositorParent* aCompositorParent,
CompositorChild* aCompositorChild,
Thread* aCompositorThread)
{
@ -120,6 +120,27 @@ static void DestroyCompositor(CompositorParent* aCompositorParent,
aCompositorChild->Release();
}
void nsBaseWidget::DestroyCompositor()
{
if (mCompositorChild) {
mCompositorChild->SendWillStop();
// The call just made to SendWillStop can result in IPC from the
// CompositorParent to the CompositorChild (e.g. caused by the destruction
// of shared memory). We need to ensure this gets processed by the
// CompositorChild before it gets destroyed. It suffices to ensure that
// events already in the MessageLoop get processed before the
// CompositorChild is destroyed, so we add a task to the MessageLoop to
// handle compositor desctruction.
MessageLoop::current()->PostTask(FROM_HERE,
NewRunnableFunction(DeferredDestroyCompositor, mCompositorParent,
mCompositorChild, mCompositorThread));
// The DestroyCompositor task we just added to the MessageLoop will handle
// releasing mCompositorParent and mCompositorChild.
mCompositorParent.forget();
mCompositorChild.forget();
}
}
//-------------------------------------------------------------------------
//
@ -138,25 +159,7 @@ nsBaseWidget::~nsBaseWidget()
mLayerManager = nsnull;
}
if (mCompositorChild) {
mCompositorChild->SendWillStop();
// The call just made to SendWillStop can result in IPC from the
// CompositorParent to the CompositorChild (e.g. caused by the destruction
// of shared memory). We need to ensure this gets processed by the
// CompositorChild before it gets destroyed. It suffices to ensure that
// events already in the MessageLoop get processed before the
// CompositorChild is destroyed, so we add a task to the MessageLoop to
// handle compositor desctruction.
MessageLoop::current()->
PostTask(FROM_HERE,
NewRunnableFunction(DestroyCompositor, mCompositorParent,
mCompositorChild, mCompositorThread));
// The DestroyCompositor task we just added to the MessageLoop will handle
// releasing mCompositorParent and mCompositorChild.
mCompositorParent.forget();
mCompositorChild.forget();
}
DestroyCompositor();
#ifdef NOISY_WIDGET_LEAKS
gNumWidgets--;

View File

@ -266,6 +266,17 @@ protected:
BasicLayerManager* CreateBasicLayerManager();
protected:
/**
* Starts the OMTC compositor destruction sequence.
*
* When this function returns, the compositor should not be
* able to access the opengl context anymore.
* It is safe to call it several times if platform implementations
* require the compositor to be destroyed before ~nsBaseWidget is
* reached (This is the case with gtk2 for instance).
*/
void DestroyCompositor();
void* mClientData;
ViewWrapper* mViewWrapperPtr;
EVENT_CALLBACK mEventCallback;