summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2014-08-17 19:58:41 +0200
committerMichael Stahl <mstahl@redhat.com>2014-08-20 16:40:09 +0200
commit37ea2c99b9374f956d2a73bf1c085f2b47d53add (patch)
treeb32bd17ae2d6ea307f27cf1e5b0c33ae441583ad
parent102348fcd17ab4a862d6f15565f97d8a88cd9231 (diff)
fdo#72695: avoid double-free race condition for SwXFrame
The problem is that Modify() may be called from ~SwFmt while another thread is waiting on SolarMutex in the ~SwXFrame or derived class destructor, so the ref-count is 0 and the uno::Reference in Modify() will cause a double-free. Since ClientModify() does some re-parenting of listeners, it is at first glance better to call Modify() in this situation (although it is quite possible that it actually doesn't matter), so don't avoid the call in ~SwFrmFmt by adding a SwClient* member there, but put a weak reference to itself into SwXFrame so it can check if it's still alive... Change-Id: I492bb8a8557af5fc725fdb7f8b21013e0886f63b
-rw-r--r--sw/source/core/unocore/unoframe.cxx23
1 files changed, 16 insertions, 7 deletions
diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx
index 225f52fd67dc..58be8ab33c5f 100644
--- a/sw/source/core/unocore/unoframe.cxx
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -1111,6 +1111,7 @@ private:
::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper
public:
+ uno::WeakReference<uno::XInterface> m_wThis;
::cppu::OInterfaceContainerHelper m_EventListeners;
Impl() : m_EventListeners(m_Mutex) { }
@@ -1249,6 +1250,8 @@ SwXFrame::CreateXFrame(SwDoc & rDoc, SwFrmFmt *const pFrmFmt)
{
pFrmFmt->SetXObject(xFrame);
}
+ // need a permanent Reference to initialize m_wThis
+ pNew->SwXFrame::m_pImpl->m_wThis = xFrame;
}
return xFrame;
}
@@ -2592,17 +2595,23 @@ throw (uno::RuntimeException, std::exception)
m_pImpl->m_EventListeners.removeInterface(xListener);
}
-void SwXFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+void SwXFrame::Modify(const SfxPoolItem* pOld, const SfxPoolItem *pNew)
{
ClientModify(this, pOld, pNew);
- if(!GetRegisteredIn())
+ if (GetRegisteredIn())
{
- mxStyleData.clear();
- mxStyleFamily.clear();
- m_pDoc = 0;
- lang::EventObject const ev(static_cast< ::cppu::OWeakObject&>(*this));
- m_pImpl->m_EventListeners.disposeAndClear(ev);
+ return; // core object still alive
}
+ mxStyleData.clear();
+ mxStyleFamily.clear();
+ m_pDoc = 0;
+ uno::Reference<uno::XInterface> const xThis(m_pImpl->m_wThis);
+ if (!xThis.is())
+ { // fdo#72695: if UNO object is already dead, don't revive it with event
+ return;
+ }
+ lang::EventObject const ev(xThis);
+ m_pImpl->m_EventListeners.disposeAndClear(ev);
}
void SwXFrame::dispose(void) throw( uno::RuntimeException, std::exception )