linguistic/source/lngsvcmgr.cxx | 148 +++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 82 deletions(-)
New commits: commit bc74f11ee12112237af8e8ba5adbe01198bba06f Author: Caolán McNamara <[email protected]> AuthorDate: Tue Oct 7 17:13:29 2025 +0100 Commit: Caolán McNamara <[email protected]> CommitDate: Tue Oct 7 20:20:58 2025 +0200 return of macos crash on grammar uno::Reference::release not clear to me why this happens, xFactory is null before the throw in GetAvailableGrammarSvcs_Impl() and apparently non-null after, but a lldb watch refuses to capture when/if it changes. expanding the ternary into if/else + set appears to work. Rewrite these three cases with a shared helper template to make it smaller and possibly prettier and avoid the problem on macos. * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=257, address=0x2e006e00750073) * frame #0: 0x0000006e00750073 frame #1: 0x00000001482b2910 libmergedlo.dylib`LngSvcMgr::GetAvailableGrammarSvcs_Impl() [inlined] com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory>::~Reference(this=<unavailable>) at Reference.hxx:114:22 frame #2: 0x00000001482b28fc libmergedlo.dylib`LngSvcMgr::GetAvailableGrammarSvcs_Impl() [inlined] com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory>::~Reference(this=<unavailable>) at Reference.hxx:112:1 frame #3: 0x00000001482b28fc libmergedlo.dylib`LngSvcMgr::GetAvailableGrammarSvcs_Impl(this=0x0000000131897d50) at lngsvcmgr.cxx:1040:5 frame #4: 0x00000001482b43d8 libmergedlo.dylib`LngSvcMgr::getAvailableServices(this=0x0000000131897d50, rServiceName=0x000000014b554608, rLocale=0x000000016f871150) at lngsvcmgr.cxx:1394:9 frame #5: 0x00000001482ac434 libmergedlo.dylib`LngSvcMgr::UpdateAll(this=0x0000000131897d50) at lngsvcmgr.cxx:655:46 frame #6: 0x00000001482abd38 libmergedlo.dylib`LngSvcMgr::LngSvcMgr(this=0x0000000131897d50) at lngsvcmgr.cxx:414:5 frame #7: 0x00000001482b7740 libmergedlo.dylib`::linguistic_LngSvcMgr_get_implementation(com::sun::star::uno::XComponentContext *, const com::sun::star::uno::Sequence<com::sun::star::uno::Any> &) [inlined] LngSvcMgr::LngSvcMgr(this=0x0000000131897d50) at lngsvcmgr.cxx:402:1 which looks like the same problem as seen in: commit 9ee7a841d41a5517fd567b17b936ea4c0141e157 Date: Mon Apr 27 16:32:52 2020 +0200 linguistic: make LngSvcMgr::GetAvailableGrammarSvcs_Impl() more readable It's not exactly clear why, but as a side effect, this makes a crash in uno::Reference::release() go away in the --enable-macosx-sandbox case. Change-Id: I5b04512ca8dd542a391deec62eab5262371398bb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192047 Tested-by: Jenkins Tested-by: Caolán McNamara <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> diff --git a/linguistic/source/lngsvcmgr.cxx b/linguistic/source/lngsvcmgr.cxx index 9fd9bf54c34a..291609c1871e 100644 --- a/linguistic/source/lngsvcmgr.cxx +++ b/linguistic/source/lngsvcmgr.cxx @@ -927,6 +927,22 @@ void LngSvcMgr::GetThesaurusDsp_Impl( bool bSetSvcList ) } } +namespace { + +template<typename T> uno::Reference<T> createLinguisticInstance( + const uno::Reference<uno::XComponentContext>& rContext, + const uno::Any& rCurrent) +{ + uno::Reference<lang::XSingleComponentFactory> xCompFactory(rCurrent, css::uno::UNO_QUERY); + if (xCompFactory.is()) + return uno::Reference<T>(xCompFactory->createInstanceWithContext(rContext), uno::UNO_QUERY_THROW); + uno::Reference<lang::XSingleServiceFactory> xFactory(rCurrent, css::uno::UNO_QUERY); + if (xFactory) + return uno::Reference<T>(xFactory->createInstance(), uno::UNO_QUERY_THROW); + return nullptr; +} + +} void LngSvcMgr::GetAvailableSpellSvcs_Impl() { @@ -948,40 +964,30 @@ void LngSvcMgr::GetAvailableSpellSvcs_Impl() while (xEnum->hasMoreElements()) { uno::Any aCurrent = xEnum->nextElement(); - uno::Reference< lang::XSingleComponentFactory > xCompFactory; - uno::Reference< lang::XSingleServiceFactory > xFactory; - - xCompFactory.set(aCurrent, css::uno::UNO_QUERY); - if (!xCompFactory.is()) + try { - xFactory.set(aCurrent, css::uno::UNO_QUERY); + auto xSvc = createLinguisticInstance<linguistic2::XSpellChecker>(xContext, aCurrent); + if (!xSvc) + continue; + + OUString aImplName; + std::vector< LanguageType > aLanguages; + uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); + if (xInfo.is()) + aImplName = xInfo->getImplementationName(); + SAL_WARN_IF( aImplName.isEmpty(), "linguistic", "empty implementation name" ); + uno::Sequence<lang::Locale> aLocaleSequence(xSvc->getLocales()); + aLanguages = LocaleSeqToLangVec( aLocaleSequence ); + + pAvailSpellSvcs->push_back( SvcInfo( aImplName, std::move(aLanguages) ) ); } - if ( xCompFactory.is() || xFactory.is() ) + catch (const uno::Exception &) { - try - { - uno::Reference< linguistic2::XSpellChecker > xSvc( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY_THROW ); - - OUString aImplName; - std::vector< LanguageType > aLanguages; - uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); - if (xInfo.is()) - aImplName = xInfo->getImplementationName(); - SAL_WARN_IF( aImplName.isEmpty(), "linguistic", "empty implementation name" ); - uno::Sequence<lang::Locale> aLocaleSequence(xSvc->getLocales()); - aLanguages = LocaleSeqToLangVec( aLocaleSequence ); - - pAvailSpellSvcs->push_back( SvcInfo( aImplName, std::move(aLanguages) ) ); - } - catch (const uno::Exception &) - { - SAL_WARN( "linguistic", "createInstance failed" ); - } + SAL_WARN( "linguistic", "createInstance failed" ); } } } - void LngSvcMgr::GetAvailableGrammarSvcs_Impl() { if (pAvailGrammarSvcs) @@ -1002,41 +1008,27 @@ void LngSvcMgr::GetAvailableGrammarSvcs_Impl() while (xEnum->hasMoreElements()) { uno::Any aCurrent = xEnum->nextElement(); - uno::Reference< lang::XSingleComponentFactory > xCompFactory; - uno::Reference< lang::XSingleServiceFactory > xFactory; - - xCompFactory.set(aCurrent, css::uno::UNO_QUERY); - if (!xCompFactory.is()) + try { - xFactory.set(aCurrent, css::uno::UNO_QUERY); + auto xSvc = createLinguisticInstance<linguistic2::XProofreader>(xContext, aCurrent); + if (!xSvc) + continue; + + OUString aImplName; + std::vector< LanguageType > aLanguages; + uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); + if (xInfo.is()) + aImplName = xInfo->getImplementationName(); + SAL_WARN_IF( aImplName.isEmpty(), "linguistic", "empty implementation name" ); + uno::Sequence<lang::Locale> aLocaleSequence(xSvc->getLocales()); + aLanguages = LocaleSeqToLangVec( aLocaleSequence ); + + pAvailGrammarSvcs->push_back( SvcInfo( aImplName, std::move(aLanguages) ) ); } - if ( xCompFactory.is() || xFactory.is() ) + catch (const uno::Exception &) { - try - { - uno::Reference< linguistic2::XProofreader > xSvc( - xCompFactory.is() - ? xCompFactory->createInstanceWithContext(xContext) - : xFactory->createInstance(), - uno::UNO_QUERY_THROW); - - OUString aImplName; - std::vector< LanguageType > aLanguages; - uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); - if (xInfo.is()) - aImplName = xInfo->getImplementationName(); - SAL_WARN_IF( aImplName.isEmpty(), "linguistic", "empty implementation name" ); - uno::Sequence<lang::Locale> aLocaleSequence(xSvc->getLocales()); - aLanguages = LocaleSeqToLangVec( aLocaleSequence ); - - pAvailGrammarSvcs->push_back( SvcInfo( aImplName, std::move(aLanguages) ) ); - } - catch (const uno::Exception &) - { - SAL_WARN( "linguistic", "createInstance failed" ); - } + SAL_WARN( "linguistic", "createInstance failed" ); } - } } @@ -1060,33 +1052,25 @@ void LngSvcMgr::GetAvailableHyphSvcs_Impl() while (xEnum->hasMoreElements()) { uno::Any aCurrent = xEnum->nextElement(); - uno::Reference< lang::XSingleComponentFactory > xCompFactory; - uno::Reference< lang::XSingleServiceFactory > xFactory; - - xCompFactory.set(aCurrent, css::uno::UNO_QUERY); - if (!xCompFactory.is()) + try { - xFactory.set(aCurrent, css::uno::UNO_QUERY); + auto xSvc = createLinguisticInstance<linguistic2::XHyphenator>(xContext, aCurrent); + if (!xSvc) + continue; + + OUString aImplName; + std::vector< LanguageType > aLanguages; + uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); + if (xInfo.is()) + aImplName = xInfo->getImplementationName(); + SAL_WARN_IF( aImplName.isEmpty(), "linguistic", "empty implementation name" ); + uno::Sequence<lang::Locale> aLocaleSequence(xSvc->getLocales()); + aLanguages = LocaleSeqToLangVec( aLocaleSequence ); + pAvailHyphSvcs->push_back( SvcInfo( aImplName, std::move(aLanguages) ) ); } - if ( xCompFactory.is() || xFactory.is() ) + catch (const uno::Exception &) { - try - { - uno::Reference< linguistic2::XHyphenator > xSvc( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY_THROW ); - OUString aImplName; - std::vector< LanguageType > aLanguages; - uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); - if (xInfo.is()) - aImplName = xInfo->getImplementationName(); - SAL_WARN_IF( aImplName.isEmpty(), "linguistic", "empty implementation name" ); - uno::Sequence<lang::Locale> aLocaleSequence(xSvc->getLocales()); - aLanguages = LocaleSeqToLangVec( aLocaleSequence ); - pAvailHyphSvcs->push_back( SvcInfo( aImplName, std::move(aLanguages) ) ); - } - catch (const uno::Exception &) - { - SAL_WARN( "linguistic", "createInstance failed" ); - } + SAL_WARN( "linguistic", "createInstance failed" ); } } }
