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
a18bdb3bc0 (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.kaganski@collabora.com>
Tested-by: Jenkins
This commit is contained in:
@@ -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: */
|
||||
|
||||
@@ -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())
|
||||
css::uno::Reference<XAccessibleEventBroadcaster> const xBroadcaster(
|
||||
m_xAccessible->getAccessibleContext(), UNO_QUERY);
|
||||
if (xBroadcaster.is())
|
||||
{
|
||||
return;
|
||||
//remove the lister from accessible object
|
||||
xBroadcaster->removeAccessibleEventListener(this);
|
||||
}
|
||||
try
|
||||
{
|
||||
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
|
||||
}
|
||||
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: */
|
||||
|
||||
@@ -474,7 +474,7 @@ void AccObjectWinManager::DeleteAccObj( XAccessible* pXAcc )
|
||||
}
|
||||
if (pListener)
|
||||
{
|
||||
pListener->RemoveMeFromBroadcaster(false);
|
||||
pListener->RemoveMeFromBroadcaster();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user