linguistic/source/gciterator.cxx | 90 ++++++++++++++++++--------------------- linguistic/source/gciterator.hxx | 16 +++--- 2 files changed, 50 insertions(+), 56 deletions(-)
New commits: commit b23019c566f2cbf50dfbec71d258b3e1a9ead312 Author: Stephan Bergmann <stephan.bergm...@allotropia.de> AuthorDate: Wed Apr 3 23:32:51 2024 +0200 Commit: Stephan Bergmann <stephan.bergm...@allotropia.de> CommitDate: Thu Apr 4 07:06:00 2024 +0200 Revert "osl::Mutex->std::mutex in GrammarCheckingIterator" This reverts commit 829fa53fe877d0f0fc33d634fa7fbfbed23b7676, which started all sorts of `make check` tests to hang for me due to a recursive locking attempt in > #5 std::mutex::lock (this=0x7f6af81e62c0) at ~/gcc/inst/include/c++/14.0.1/bits/std_mutex.h:113 > #6 std::unique_lock<std::mutex>::lock (this=<synthetic pointer>) at ~/gcc/inst/include/c++/14.0.1/bits/unique_lock.h:147 > #7 std::unique_lock<std::mutex>::unique_lock (this=<synthetic pointer>, __m=...) at ~/gcc/inst/include/c++/14.0.1/bits/unique_lock.h:73 > #8 GrammarCheckingIterator::NextDocId (this=0x7f6af81e6260) at linguistic/source/gciterator.cxx:317 > #9 GrammarCheckingIterator::GetOrCreateDocId (this=this@entry=0x7f6af81e6260, xComponent=uno::Reference to (SwXTextDocument *) 0x7f6af8430ec8) at linguistic/source/gciterator.cxx:339 > #10 0x00007f6b3b9e9da9 in GrammarCheckingIterator::startProofreading (this=0x7f6af81e6260, xDoc=<optimized out>, xIteratorProvider=<optimized out>) at linguistic/source/gciterator.cxx:773 > #11 0x00007f6b16441ec3 in SwDoc::StartGrammarChecking (this=<optimized out>, bSkipStart=bSkipStart@entry=false) at sw/source/core/doc/docnew.cxx:180 > #12 0x00007f6b164c4eae in sw::DocumentTimerManager::DoIdleJobs (this=0x7f6afad005a0) at sw/source/core/doc/DocumentTimerManager.cxx:169 > #13 0x00007f6b3e83a68b in Scheduler::CallbackTaskScheduling () at vcl/source/app/scheduler.cxx:509 > #14 0x00007f6b3eb1725f in SalTimer::CallCallback (this=<optimized out>) at vcl/inc/saltimer.hxx:54 > #15 SvpSalInstance::CheckTimeout (this=this@entry=0xffebe0, bExecuteTimers=bExecuteTimers@entry=true) at vcl/headless/svpinst.cxx:157 > #16 0x00007f6b3eb1761d in SvpSalInstance::ImplYield (this=this@entry=0xffebe0, bWait=bWait@entry=true, bHandleAllCurrentEvents=bHandleAllCurrentEvents@entry=false) at vcl/headless/svpinst.cxx:395 > #17 0x00007f6b3eb17cd5 in SvpSalInstance::DoYield (this=0xffebe0, bWait=<optimized out>, bHandleAllCurrentEvents=<optimized out>) at vcl/headless/svpinst.cxx:467 > #18 0x00007f6b3e86aa44 in ImplYield (i_bWait=true, i_bAllEvents=false) at vcl/source/app/svapp.cxx:394 > #19 0x00007f6b3e86b13b in Application::Execute () at vcl/source/app/svapp.cxx:369 > #20 0x00007f6b3c8e715f in desktop::Desktop::Main (this=0x7ffe5e22fcb0) at desktop/source/app/app.cxx:1615 > #21 0x00007f6b3e87e6fb in ImplSVMain () at vcl/source/app/svmain.cxx:229 > #22 0x00007f6b3e87e9c5 in SVMain () at vcl/source/app/svmain.cxx:261 > #23 0x00007f6b3c91de37 in soffice_main () at desktop/source/app/sofficemain.cxx:93 > #24 0x000000000040078b in sal_main () at desktop/source/app/main.c:51 > #25 main (argc=argc@entry=8, argv=argv@entry=0x7ffe5e22feb8) at desktop/source/app/main.c:49 Change-Id: I60b8b0ba00cae691d6089325e4379a86221dc95b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165764 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <stephan.bergm...@allotropia.de> diff --git a/linguistic/source/gciterator.cxx b/linguistic/source/gciterator.cxx index bf37df637f4b..ad85bab95953 100644 --- a/linguistic/source/gciterator.cxx +++ b/linguistic/source/gciterator.cxx @@ -273,11 +273,19 @@ css::uno::Any SAL_CALL LngXStringKeyMap::getValueByIndex(::sal_Int32 nIndex) } +osl::Mutex& GrammarCheckingIterator::MyMutex() +{ + static osl::Mutex SINGLETON; + return SINGLETON; +} + GrammarCheckingIterator::GrammarCheckingIterator() : m_bEnd( false ), m_bGCServicesChecked( false ), m_nDocIdCounter( 0 ), - m_thread(nullptr) + m_thread(nullptr), + m_aEventListeners( MyMutex() ), + m_aNotifyListeners( MyMutex() ) { } @@ -291,7 +299,7 @@ void GrammarCheckingIterator::TerminateThread() { oslThread t; { - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); t = m_thread; m_thread = nullptr; m_bEnd = true; @@ -314,14 +322,13 @@ bool GrammarCheckingIterator::joinThreads() sal_Int32 GrammarCheckingIterator::NextDocId() { - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); m_nDocIdCounter += 1; return m_nDocIdCounter; } OUString GrammarCheckingIterator::GetOrCreateDocId( - std::unique_lock<std::mutex>& /*rGuard*/, const uno::Reference< lang::XComponent > &xComponent ) { // internal method; will always be called with locked mutex @@ -347,7 +354,6 @@ OUString GrammarCheckingIterator::GetOrCreateDocId( void GrammarCheckingIterator::AddEntry( - std::unique_lock<std::mutex>& /*rGuard*/, const uno::Reference< text::XFlatParagraphIterator >& xFlatParaIterator, const uno::Reference< text::XFlatParagraph >& xFlatPara, const OUString & rDocId, @@ -367,6 +373,7 @@ void GrammarCheckingIterator::AddEntry( aNewFPEntry.m_bAutomatic = bAutomatic; // add new entry to the end of this queue + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); if (!m_thread) m_thread = osl_createThread( lcl_workerfunc, this ); m_aFPEntriesQueue.push_back( aNewFPEntry ); @@ -479,8 +486,7 @@ void GrammarCheckingIterator::ProcessResult( // other sentences left to be checked in this paragraph? if (rRes.nStartOfNextSentencePosition < rRes.aText.getLength()) { - std::unique_lock aGuard(m_aMutex); - AddEntry( aGuard, rxFlatParagraphIterator, rRes.xFlatParagraph, rRes.aDocumentIdentifier, rRes.nStartOfNextSentencePosition, bIsAutomaticChecking ); + AddEntry( rxFlatParagraphIterator, rRes.xFlatParagraph, rRes.aDocumentIdentifier, rRes.nStartOfNextSentencePosition, bIsAutomaticChecking ); } else // current paragraph finished { @@ -496,11 +502,8 @@ void GrammarCheckingIterator::ProcessResult( { // we need to continue with the next paragraph if (rxFlatParagraphIterator.is()) - { - std::unique_lock aGuard(m_aMutex); - AddEntry(aGuard, rxFlatParagraphIterator, rxFlatParagraphIterator->getNextPara(), + AddEntry(rxFlatParagraphIterator, rxFlatParagraphIterator->getNextPara(), rRes.aDocumentIdentifier, 0, bIsAutomaticChecking); - } } } @@ -528,11 +531,13 @@ GrammarCheckingIterator::getServiceForLocale(const lang::Locale& rLocale) const uno::Reference< linguistic2::XProofreader > GrammarCheckingIterator::GetGrammarChecker( - std::unique_lock<std::mutex>& /*rGuard*/, lang::Locale &rLocale ) { uno::Reference< linguistic2::XProofreader > xRes; + // ---- THREAD SAFE START ---- + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); + // check supported locales for each grammarchecker if not already done if (!m_bGCServicesChecked) { @@ -585,6 +590,7 @@ uno::Reference< linguistic2::XProofreader > GrammarCheckingIterator::GetGrammarC SAL_INFO("linguistic", "No grammar checker found for \"" << LanguageTag::convertToBcp47(rLocale, false) << "\""); } + // ---- THREAD SAFE END ---- return xRes; } @@ -611,7 +617,7 @@ void GrammarCheckingIterator::DequeueAndCheck() // ---- THREAD SAFE START ---- bool bQueueEmpty = false; { - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); if (m_bEnd) { break; @@ -628,7 +634,7 @@ void GrammarCheckingIterator::DequeueAndCheck() OUString aCurDocId; // ---- THREAD SAFE START ---- { - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); aFPEntryItem = m_aFPEntriesQueue.front(); xFPIterator = aFPEntryItem.m_xParaIterator; xFlatPara = aFPEntryItem.m_xPara; @@ -653,7 +659,7 @@ void GrammarCheckingIterator::DequeueAndCheck() // ---- THREAD SAFE START ---- { - std::unique_lock aGuard( m_aMutex ); + osl::ClearableMutexGuard aGuard(MyMutex()); sal_Int32 nStartPos = aFPEntryItem.m_nStartIndex; sal_Int32 nSuggestedEnd @@ -663,10 +669,10 @@ void GrammarCheckingIterator::DequeueAndCheck() "nSuggestedEndOfSentencePos calculation failed?"); uno::Reference<linguistic2::XProofreader> xGC = - GetGrammarChecker(aGuard, aCurLocale); + GetGrammarChecker(aCurLocale); if (xGC.is()) { - aGuard.unlock(); + aGuard.clear(); uno::Sequence<beans::PropertyValue> const aProps( lcl_makeProperties(xFlatPara, PROOFINFO_MARK_PARAGRAPH)); aRes = xGC->doProofreading(aCurDocId, aCurTxt, aCurLocale, @@ -712,8 +718,7 @@ void GrammarCheckingIterator::DequeueAndCheck() // the paragraph changed meanwhile... (and maybe is still edited) // thus we simply continue to ask for the next to be checked. uno::Reference< text::XFlatParagraph > xFlatParaNext( xFPIterator->getNextPara() ); - std::unique_lock aGuard(m_aMutex); - AddEntry( aGuard, xFPIterator, xFlatParaNext, aCurDocId, 0, aFPEntryItem.m_bAutomatic ); + AddEntry( xFPIterator, xFlatParaNext, aCurDocId, 0, aFPEntryItem.m_bAutomatic ); } } catch (css::uno::Exception &) @@ -724,7 +729,7 @@ void GrammarCheckingIterator::DequeueAndCheck() // ---- THREAD SAFE START ---- { - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); m_aCurCheckedDocId.clear(); } // ---- THREAD SAFE END ---- @@ -733,7 +738,7 @@ void GrammarCheckingIterator::DequeueAndCheck() { // ---- THREAD SAFE START ---- { - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); if (m_bEnd) { break; @@ -767,13 +772,13 @@ void SAL_CALL GrammarCheckingIterator::startProofreading( uno::Reference< lang::XComponent > xComponent( xDoc, uno::UNO_QUERY ); // ---- THREAD SAFE START ---- - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); if (xPara.is() && xComponent.is()) { - OUString aDocId = GetOrCreateDocId( aGuard, xComponent ); + OUString aDocId = GetOrCreateDocId( xComponent ); // create new entry and add it to queue - AddEntry( aGuard, xFPIterator, xPara, aDocId, 0, bAutomatic ); + AddEntry( xFPIterator, xPara, aDocId, 0, bAutomatic ); } // ---- THREAD SAFE END ---- } @@ -810,12 +815,12 @@ linguistic2::ProofreadingResult SAL_CALL GrammarCheckingIterator::checkSentenceA // ---- THREAD SAFE START ---- { - std::unique_lock aGuard( m_aMutex ); - aDocId = GetOrCreateDocId( aGuard, xComponent ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); + aDocId = GetOrCreateDocId( xComponent ); nSuggestedEndOfSentencePos = GetSuggestedEndOfSentence( rText, nStartPos, aCurLocale ); DBG_ASSERT( nSuggestedEndOfSentencePos > nStartPos, "nSuggestedEndOfSentencePos calculation failed?" ); - xGC = GetGrammarChecker( aGuard, aCurLocale ); + xGC = GetGrammarChecker( aCurLocale ); } // ---- THREAD SAFE START ---- sal_Int32 nEndPos = -1; @@ -922,7 +927,7 @@ sal_Bool SAL_CALL GrammarCheckingIterator::isProofreading( const uno::Reference< uno::XInterface >& xDoc ) { // ---- THREAD SAFE START ---- - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); bool bRes = false; @@ -973,9 +978,7 @@ void SAL_CALL GrammarCheckingIterator::processLinguServiceEvent( { uno::Reference< uno::XInterface > xThis( getXWeak() ); linguistic2::LinguServiceEvent aEvent( xThis, linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN ); - std::unique_lock aGuard( m_aMutex ); m_aNotifyListeners.notifyEach( - aGuard, &linguistic2::XLinguServiceEventListener::processLinguServiceEvent, aEvent); } @@ -996,8 +999,7 @@ sal_Bool SAL_CALL GrammarCheckingIterator::addLinguServiceEventListener( { if (xListener.is()) { - std::unique_lock aGuard( m_aMutex ); - m_aNotifyListeners.addInterface( aGuard, xListener ); + m_aNotifyListeners.addInterface( xListener ); } return true; } @@ -1008,8 +1010,7 @@ sal_Bool SAL_CALL GrammarCheckingIterator::removeLinguServiceEventListener( { if (xListener.is()) { - std::unique_lock aGuard( m_aMutex ); - m_aNotifyListeners.removeInterface( aGuard, xListener ); + m_aNotifyListeners.removeInterface( xListener ); } return true; } @@ -1018,16 +1019,13 @@ sal_Bool SAL_CALL GrammarCheckingIterator::removeLinguServiceEventListener( void SAL_CALL GrammarCheckingIterator::dispose() { lang::EventObject aEvt( static_cast<linguistic2::XProofreadingIterator *>(this) ); - { - std::unique_lock aGuard( m_aMutex ); - m_aEventListeners.disposeAndClear( aGuard, aEvt ); - } + m_aEventListeners.disposeAndClear( aEvt ); TerminateThread(); // ---- THREAD SAFE START ---- { - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); // release all UNO references @@ -1050,8 +1048,7 @@ void SAL_CALL GrammarCheckingIterator::addEventListener( { if (xListener.is()) { - std::unique_lock aGuard( m_aMutex ); - m_aEventListeners.addInterface( aGuard, xListener ); + m_aEventListeners.addInterface( xListener ); } } @@ -1061,8 +1058,7 @@ void SAL_CALL GrammarCheckingIterator::removeEventListener( { if (xListener.is()) { - std::unique_lock aGuard( m_aMutex ); - m_aEventListeners.removeInterface( aGuard, xListener ); + m_aEventListeners.removeInterface( xListener ); } } @@ -1081,7 +1077,7 @@ void SAL_CALL GrammarCheckingIterator::disposing( const lang::EventObject &rSour if (xDoc.is()) { // ---- THREAD SAFE START ---- - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); m_aDocIdMap.erase( xDoc.get() ); // ---- THREAD SAFE END ---- } @@ -1155,7 +1151,7 @@ void GrammarCheckingIterator::GetConfiguredGCSvcs_Impl() { // ---- THREAD SAFE START ---- - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); m_aGCImplNamesByLang.swap(aTmpGCImplNamesByLang); // ---- THREAD SAFE END ---- } @@ -1185,7 +1181,7 @@ void GrammarCheckingIterator::SetServiceList( const lang::Locale &rLocale, const uno::Sequence< OUString > &rSvcImplNames ) { - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); OUString sBcp47 = LanguageTag::convertToBcp47(rLocale, false); OUString aImplName; @@ -1205,7 +1201,7 @@ void GrammarCheckingIterator::SetServiceList( uno::Sequence< OUString > GrammarCheckingIterator::GetServiceList( const lang::Locale &rLocale ) const { - std::unique_lock aGuard( m_aMutex ); + ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() ); const OUString aImplName = getServiceForLocale(rLocale).first; // there is only one grammar checker per language diff --git a/linguistic/source/gciterator.hxx b/linguistic/source/gciterator.hxx index e56b0ea53e98..62b3a53af8fa 100644 --- a/linguistic/source/gciterator.hxx +++ b/linguistic/source/gciterator.hxx @@ -29,13 +29,13 @@ #include <com/sun/star/util/XChangesBatch.hpp> #include <cppuhelper/implbase.hxx> -#include <mutex> +#include <osl/mutex.hxx> #include <osl/conditn.hxx> #include <osl/thread.h> #include <com/sun/star/uno/Any.hxx> #include <comphelper/lok.hxx> -#include <comphelper/interfacecontainer4.hxx> +#include <comphelper/interfacecontainer3.hxx> #include <i18nlangtag/lang.h> #include <map> @@ -84,8 +84,6 @@ class GrammarCheckingIterator: public LinguDispatcher, public comphelper::LibreOfficeKit::ThreadJoinable { - mutable std::mutex m_aMutex; - //the queue is keeping track of all sentences to be checked //every element of this queue is a FlatParagraphEntry struct-object typedef std::deque< FPEntry > FPQueue_t; @@ -116,8 +114,9 @@ class GrammarCheckingIterator: oslThread m_thread; //! beware of initialization order! - comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListeners; - comphelper::OInterfaceContainerHelper4<css::linguistic2::XLinguServiceEventListener> m_aNotifyListeners; + static osl::Mutex& MyMutex(); + comphelper::OInterfaceContainerHelper3<css::lang::XEventListener> m_aEventListeners; + comphelper::OInterfaceContainerHelper3<css::linguistic2::XLinguServiceEventListener> m_aNotifyListeners; css::uno::Reference< css::i18n::XBreakIterator > m_xBreakIterator; mutable css::uno::Reference< css::util::XChangesBatch > m_xUpdateAccess; @@ -125,10 +124,9 @@ class GrammarCheckingIterator: void TerminateThread(); sal_Int32 NextDocId(); - OUString GetOrCreateDocId( std::unique_lock<std::mutex>& rGuard, const css::uno::Reference< css::lang::XComponent > &xComp ); + OUString GetOrCreateDocId( const css::uno::Reference< css::lang::XComponent > &xComp ); void AddEntry( - std::unique_lock<std::mutex>& rGuard, const css::uno::Reference< css::text::XFlatParagraphIterator >& xFlatParaIterator, const css::uno::Reference< css::text::XFlatParagraph >& xFlatPara, const OUString &rDocId, sal_Int32 nStartIndex, bool bAutomatic ); @@ -140,7 +138,7 @@ class GrammarCheckingIterator: sal_Int32 GetSuggestedEndOfSentence( const OUString &rText, sal_Int32 nSentenceStartPos, const css::lang::Locale &rLocale ); void GetConfiguredGCSvcs_Impl(); - css::uno::Reference< css::linguistic2::XProofreader > GetGrammarChecker( std::unique_lock<std::mutex>& rGuard, css::lang::Locale & rLocale ); + css::uno::Reference< css::linguistic2::XProofreader > GetGrammarChecker( css::lang::Locale & rLocale ); css::uno::Reference< css::util::XChangesBatch > const & GetUpdateAccess() const;