summaryrefslogtreecommitdiff
path: root/sw
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 /sw
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
Diffstat (limited to 'sw')
-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 )