sw/source/core/unocore/unoparagraph.cxx |   22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

New commits:
commit 1e5e65715cf053deb7d52e62dd598ac51cea5ee6
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Thu Nov 10 13:16:11 2022 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Thu Nov 10 20:14:13 2022 +0100

    Revert "tdf#126788 remove weak m_wThis reference"
    
    Causes race condition
    
    And add comment so I don't have think through this again.
    
    This reverts commit 2ae53eb5dcbe0a3c5b4dc5323639a11878a38101.
    
    Change-Id: Id18a7313e363a4ce4930b01fc760a3746b35a711
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142548
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/sw/source/core/unocore/unoparagraph.cxx 
b/sw/source/core/unocore/unoparagraph.cxx
index d2f3db46680e..7861f831f9a7 100644
--- a/sw/source/core/unocore/unoparagraph.cxx
+++ b/sw/source/core/unocore/unoparagraph.cxx
@@ -114,6 +114,7 @@ class SwXParagraph::Impl
 {
 public:
     SwXParagraph& m_rThis;
+    unotools::WeakReference<SwXParagraph> m_wThis;
     std::mutex m_Mutex; // just for OInterfaceContainerHelper4
     ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> 
m_EventListeners;
     SfxItemPropertySet const& m_rPropSet;
@@ -191,8 +192,19 @@ void SwXParagraph::Impl::Notify(const SfxHint& rHint)
         std::unique_lock aGuard(m_Mutex);
         if (m_EventListeners.getLength(aGuard) != 0)
         {
-            uno::Reference<uno::XInterface> const xThis(m_rThis);
-            lang::EventObject const ev(m_rThis);
+            // fdo#72695: if UNO object is already dead, don't revive it with 
event
+            // The specific pattern we are guarding against is this:
+            // [1] Thread1 takes the SolarMutex
+            // [2] Thread2 decrements the SwXParagraph reference count, and 
calls the
+            //     SwXParagraph destructor, which tries to take the 
SolarMutex, and blocks
+            // [3] Thread1 destroys a SwTextNode, which calls this Notify 
event, which results
+            //     in a double-free if we construct the xThis object.
+            uno::Reference<uno::XInterface> const xThis(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_EventListeners.disposeAndClear(aGuard, ev);
         }
     }
@@ -214,10 +226,6 @@ SwXParagraph::SwXParagraph(
 
 SwXParagraph::~SwXParagraph()
 {
-    SolarMutexGuard aGuard;
-    // need to stop listening before destruction so we don't get DYING events
-    // that might then revive the SwXParagraph when constructing an EventObject
-    m_pImpl->EndListeningAll();
 }
 
 const SwTextNode * SwXParagraph::GetTextNode() const
@@ -264,6 +272,8 @@ SwXParagraph::CreateXParagraph(SwDoc & rDoc, SwTextNode 
*const pTextNode,
     {
         pTextNode->SetXParagraph(xParagraph);
     }
+    // need a permanent Reference to initialize m_wThis
+    pXPara->m_pImpl->m_wThis = xParagraph.get();
     return xParagraph;
 }
 

Reply via email to