sfx2/source/doc/sfxbasemodel.cxx |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

New commits:
commit 69cfa8a71faec56cd6f7708f14f5e3794827fc04
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Jun 25 00:07:28 2025 +0500
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Wed Jun 25 10:14:45 2025 +0200

    SfxBaseModel: allow repeated dispose()
    
    A crash seen at shutdown with this call stack:
    
      ucrtbased.dll!terminate() Line 59
      vcruntime140_1d.dll!FindHandler<__FrameHandler4>()    Unknown
      vcruntime140_1d.dll!__InternalCxxFrameHandler<class 
__FrameHandler4>(struct EHExceptionRecord *,unsigned __int64 *,struct _CONTEXT 
*,struct _xDISPATCHER_CONTEXT *,struct FH4::FuncInfo4 *,int,unsigned __int64 
*,unsigned char)      Unknown
      vcruntime140_1d.dll!__InternalCxxFrameHandlerWrapper<class 
__FrameHandler4>(struct EHExceptionRecord *,unsigned __int64 *,struct _CONTEXT 
*,struct _xDISPATCHER_CONTEXT *,struct FH4::FuncInfo4 *,int,unsigned __int64 
*,unsigned char)       Unknown
      vcruntime140_1d.dll!__CxxFrameHandler4()      Unknown
      ntdll.dll!RtlpExecuteHandlerForException()    Unknown
      ntdll.dll!RtlDispatchException()      Unknown
      ntdll.dll!RtlRaiseException() Unknown
      KernelBase.dll!RaiseException()       Unknown
      vcruntime140d.dll!_CxxThrowException(void * pExceptionObject, const 
_s__ThrowInfo * pThrowInfo) Line 79
      sfxlo.dll!SfxBaseModel::MethodEntryCheck(const bool i_mustBeInitialized) 
Line 3065
      sfxlo.dll!SfxModelGuard::SfxModelGuard(const SfxBaseModel & i_rModel, 
const SfxModelGuard::AllowedModelState i_eState) Line 76
      sfxlo.dll!SfxBaseModel::dispose() Line 740
      cppuhelper3MSC.dll!cppu::`anonymous 
namespace'::ComponentContext::disposing(std::unique_lock<std::mutex> & rGuard) 
Line 423
      cppuhelper3MSC.dll!cppuhelper::WeakComponentImplHelperBase2::dispose() 
Line 27
      
cppuhelper3MSC.dll!cppuhelper::WeakComponentImplHelper2<com::sun::star::uno::XComponentContext,com::sun::star::container::XNameContainer>::dispose()
 Line 87
      cppuhelper3MSC.dll!cppu::`anonymous 
namespace'::DisposingForwarder::disposing(const 
com::sun::star::lang::EventObject & __formal) Line 117
      
cppuhelper3MSC.dll!cppuhelper::OInterfaceContainerHelper4<com::sun::star::lang::XEventListener>::disposeAndClear(std::unique_lock<std::mutex>
 & rGuard, const com::sun::star::lang::EventObject & rEvt) Line 402
      cppuhelper3MSC.dll!cppuhelper::WeakComponentImplHelperBase2::dispose() 
Line 31
      
cppuhelper3MSC.dll!cppuhelper::WeakComponentImplHelper2<com::sun::star::uno::XComponentContext,com::sun::star::container::XNameContainer>::dispose()
 Line 87
      sofficeapp.dll!desktop::Desktop::DeInit() Line 606
      vcllo.dll!DeInitVCL() Line 530
      vcllo.dll!ImplSVMain() Line 244
      vcllo.dll!SVMain() Line 250
      sofficeapp.dll!soffice_main() Line 122
      soffice.bin!sal_main() Line 51        C
      soffice.bin!main(int argc, char * * argv) Line 49     C
      soffice.bin!invoke_main() Line 79
      soffice.bin!__scrt_common_main_seh() Line 288
      soffice.bin!__scrt_common_main() Line 331
      soffice.bin!mainCRTStartup(void * __formal) Line 17
      kernel32.dll!BaseThreadInitThunk()    Unknown
      ntdll.dll!RtlUserThreadStart()        Unknown
    
    where impl_isDisposed() returned true in SfxBaseModel::MethodEntryCheck.
    
    The documentation for XComponent::dispose() says:
    
    > The owner of an object calls this method to explicitly free all
    > resources kept by this object and thus break cyclic references.
    > ...
    > After this method has been called, the object should behave as
    > passive as possible, thus it should ignore all calls in case it
    > can comply with its specification
    > ...
    > For some objects no real owner can be identified, thus it can be
    > disposed from multiple reference holders. In this case the object
    > should be able to cope with multiple dispose()-calls (which are
    > inevitable in a multithreaded environment).
    
    Let's handle multiple dispose()-calls: this fulfils the "behave as
    passive as possible" requirement, because it complies with the
    specification: the repeated calls don't leave open resources and
    cyclic references after ignoring them; and also fits into the last
    clause.
    
    SfxModelGuard is not needed here. It was called with E_INITIALIZING,
    which means "do not throw in not initialized"; and that translates
    to "only throw when disposed". But that's exactly the state which
    we want to handle gracefully now.
    
    And SfxModelGuard uses SolarMutexClearableGuard; so we also should lock
    solar mutex here.
    
    Change-Id: I114e92257a9cf87e1e23018f296a1fa0f013877b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186917
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    (cherry picked from commit 9f215024f6a3909228ff50439782e5ffa30ddb14)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186925
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx
index 8b21c5f74ba5..2ee1fefb4b54 100644
--- a/sfx2/source/doc/sfxbasemodel.cxx
+++ b/sfx2/source/doc/sfxbasemodel.cxx
@@ -737,7 +737,9 @@ void SAL_CALL SfxBaseModel::setParent(const Reference< 
XInterface >& Parent)
 
 void SAL_CALL SfxBaseModel::dispose()
 {
-    SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
+    SolarMutexGuard aGuard;
+    if (impl_isDisposed())
+        return;
 
     if  ( !m_pData->m_bClosed )
     {

Reply via email to