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 ) {