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" );
         }
     }
 }

Reply via email to