winaccessibility/inc/AccEventListener.hxx               |    2 
 winaccessibility/source/service/AccEventListener.cxx    |   43 +++++-----------
 winaccessibility/source/service/AccObjectWinManager.cxx |    2 
 3 files changed, 18 insertions(+), 29 deletions(-)

New commits:
commit af8c52479064a72623f2d8eb9f479b741a2c735c
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Jun 5 20:49:50 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Jun 7 11:46:45 2025 +0200

    tdf#166875: Don't notify broadcaster from its disposing notification
    
    An assert failed in debugging, when closing print preview in Writer:
    
      ucrtbased.dll!_wassert(const wchar_t * expression, const wchar_t * 
file_name, unsigned int line_number) Line 443
      comphelper.dll!`anonymous namespace'::implLookupClient(const unsigned 
long nClient, 
std::_List_iterator<std::_List_val<std::_List_simple_types<std::pair<unsigned 
long const 
,comphelper::OInterfaceContainerHelper4<com::sun::star::accessibility::XAccessibleEventListener>>>>>
 & rPos) Line 140
      
comphelper.dll!comphelper::AccessibleEventNotifier::removeEventListener(const 
unsigned long _nClient, const 
com::sun::star::uno::Reference<com::sun::star::accessibility::XAccessibleEventListener>
 & _rxListener) Line 229
      swlo.dll!SwAccessibleContext::removeAccessibleEventListener(const 
com::sun::star::uno::Reference<com::sun::star::accessibility::XAccessibleEventListener>
 & xListener) Line 746
      winaccessibility.dll!AccEventListener::RemoveMeFromBroadcaster(bool 
isNotifyDestroy) Line 262
      winaccessibility.dll!AccEventListener::disposing(const 
com::sun::star::lang::EventObject & __formal) Line 287
      
comphelper.dll!comphelper::OInterfaceContainerHelper4<com::sun::star::accessibility::XAccessibleEventListener>::disposeAndClear(std::unique_lock<std::mutex>
 & rGuard, const com::sun::star::lang::EventObject & rEvt) Line 492
      
comphelper.dll!comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(const
 unsigned long _nClient, const 
com::sun::star::uno::Reference<com::sun::star::uno::XInterface> & 
_rxEventSource) Line 204
      swlo.dll!SwAccessibleContext::Dispose(bool bRecursive, bool 
bCanSkipInvisible) Line 1050
      swlo.dll!SwAccessibleMap::~SwAccessibleMap() Line 1571
      swlo.dll!SwAccessibleMap::`scalar deleting destructor'(unsigned int)
      swlo.dll!std::_Destroy_in_place<SwAccessibleMap>(SwAccessibleMap & _Obj) 
Line 324
      swlo.dll!std::_Ref_count_obj2<SwAccessibleMap>::_Destroy() Line 2118
      swlo.dll!std::_Ref_count_base::_Decref() Line 1161
      swlo.dll!std::_Ptr_base<SwAccessibleMap>::_Decref() Line 1385
      swlo.dll!std::shared_ptr<SwAccessibleMap>::~shared_ptr<SwAccessibleMap>() 
Line 1690
      swlo.dll!std::shared_ptr<SwAccessibleMap>::reset() Line 1737
      swlo.dll!SwViewShellImp::~SwViewShellImp() Line 108
      swlo.dll!SwViewShellImp::`scalar deleting destructor'(unsigned int)
      swlo.dll!std::default_delete<SwViewShellImp>::operator()(SwViewShellImp * 
_Ptr) Line 3309
      
swlo.dll!std::unique_ptr<SwViewShellImp,std::default_delete<SwViewShellImp>>::reset(SwViewShellImp
 * _Ptr) Line 3471
      swlo.dll!SwViewShell::~SwViewShell() Line 324
      swlo.dll!SwViewShell::`scalar deleting destructor'(unsigned int)
      swlo.dll!SwPagePreview::~SwPagePreview() Line 1235
      swlo.dll!SwPagePreview::`vector deleting destructor'(unsigned int)
      sfxlo.dll!SfxViewFrame::SwitchToViewShell_Impl(unsigned short 
nViewIdOrNo, bool bIsIndex) Line 2690
    
    SwAccessibleContext::Dispose called revokeClientNotifyDisposing,
    which removed the SwAccessibleContext's id from its map, and then
    called disposing() for all listenera of the SwAccessibleContext.
    
    When one of the listeners, in its disposing(), tried to call
    broadcaster's removeAccessibleEventListener, this violated the
    API: XEventListener::disposing documentation directly prohibits
    calling any methods of the broadcaster.
    
    This was obviously a confusion, already present in commit
    a18bdb3bc05e761704cc345a66a9d642bc4f4a0a (Integrate branch of
    IAccessible2, 2013-11-19), where the semantics of disposing()
    was thought as "the listener is disposing", when in fact, it's
    broadcaster notification about broadcaster's disposal.
    
    Change-Id: Ib7f79b2214ffeedec6b4a4c75813e4ffa2d43270
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186242
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins

diff --git a/winaccessibility/inc/AccEventListener.hxx 
b/winaccessibility/inc/AccEventListener.hxx
index 256780612964..f9153263c987 100644
--- a/winaccessibility/inc/AccEventListener.hxx
+++ b/winaccessibility/inc/AccEventListener.hxx
@@ -72,7 +72,7 @@ public:
     //get the accessible parent's role
     virtual short GetParentRole();
 
-    void RemoveMeFromBroadcaster(bool isNotifyDestroy);
+    void RemoveMeFromBroadcaster();
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccEventListener.cxx 
b/winaccessibility/source/service/AccEventListener.cxx
index 82b435e62399..aa9d291b6d6a 100644
--- a/winaccessibility/source/service/AccEventListener.cxx
+++ b/winaccessibility/source/service/AccEventListener.cxx
@@ -244,47 +244,36 @@ short AccEventListener::GetParentRole()
 /**
  *  remove the listener from accessible object
  */
-void AccEventListener::RemoveMeFromBroadcaster(bool const isNotifyDestroy)
+void AccEventListener::RemoveMeFromBroadcaster()
 {
+    if (!m_xAccessible.is())
+        return;
+
     try
     {
-        if (!m_xAccessible.is())
-        {
-            return;
-        }
-        try
+        css::uno::Reference<XAccessibleEventBroadcaster> const xBroadcaster(
+            m_xAccessible->getAccessibleContext(), UNO_QUERY);
+        if (xBroadcaster.is())
         {
-            css::uno::Reference<XAccessibleEventBroadcaster> const 
xBroadcaster(
-                m_xAccessible->getAccessibleContext(), UNO_QUERY);
-            if (xBroadcaster.is())
-            {
-                //remove the lister from accessible object
-                xBroadcaster->removeAccessibleEventListener(this);
-            }
-        }
-        catch (Exception const&)
-        { // may throw if it's already disposed - ignore that
+            //remove the lister from accessible object
+            xBroadcaster->removeAccessibleEventListener(this);
         }
-        if (isNotifyDestroy)
-        {
-            m_rObjManager.NotifyDestroy(m_xAccessible.get());
-        }
-        m_xAccessible.clear(); // release cyclic reference
     }
-    catch (...)
-    {
-        return;
+    catch (Exception const&)
+    { // may throw if it's already disposed - ignore that
     }
+
+    m_xAccessible.clear(); // release cyclic reference
 }
 
 /**
- *  this method is invoked before listener is disposed
+ *  this method is invoked before broadcaster is disposed
  */
 void AccEventListener::disposing(const css::lang::EventObject& /*Source*/)
 {
     SolarMutexGuard g;
-
-    RemoveMeFromBroadcaster(true);
+    // No method should be invoked anymore on broadcaster!
+    m_xAccessible.clear();
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccObjectWinManager.cxx 
b/winaccessibility/source/service/AccObjectWinManager.cxx
index f2253eae59e1..364f51e19bbc 100644
--- a/winaccessibility/source/service/AccObjectWinManager.cxx
+++ b/winaccessibility/source/service/AccObjectWinManager.cxx
@@ -474,7 +474,7 @@ void AccObjectWinManager::DeleteAccObj( XAccessible* pXAcc )
     }
     if (pListener)
     {
-        pListener->RemoveMeFromBroadcaster(false);
+        pListener->RemoveMeFromBroadcaster();
     }
 }
 

Reply via email to