desktop/qa/desktop_lib/test_desktop_lib.cxx |    3 ++-
 desktop/source/lib/init.cxx                 |   23 +++++++++++++++++++++++
 include/LibreOfficeKit/LibreOfficeKit.h     |    3 +++
 include/LibreOfficeKit/LibreOfficeKit.hxx   |   12 +++++++++++-
 include/comphelper/lok.hxx                  |    8 ++++++++
 linguistic/source/gciterator.cxx            |    8 ++++++++
 linguistic/source/gciterator.hxx            |    7 ++++++-
 linguistic/source/lngsvcmgr.cxx             |    8 ++++++++
 linguistic/source/lngsvcmgr.hxx             |    7 ++++++-
 9 files changed, 75 insertions(+), 4 deletions(-)

New commits:
commit 269a307da6bc4f8f4c759662703e20d4b6860f9a
Author:     Michael Meeks <michael.me...@collabora.com>
AuthorDate: Tue Feb 6 18:05:09 2024 +0000
Commit:     Michael Meeks <michael.me...@collabora.com>
CommitDate: Wed Feb 14 18:27:16 2024 +0100

    lok: implement a joinThreads function - to wind down thread pools.
    
    Necessary to do this before forking on Unix systems; use a
    dynamic_cast interface since this is all for internal use.
    
    Change-Id: I8a911322acd4ec5654eb0d14804c09d513a0bd4b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163210
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Michael Meeks <michael.me...@collabora.com>

diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx 
b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index d9809cf56ce3..c9f276a67eeb 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -3593,10 +3593,11 @@ void DesktopLOKTest::testABI()
     CPPUNIT_ASSERT_EQUAL(classOffset(17), offsetof(struct 
_LibreOfficeKitClass, trimMemory));
     CPPUNIT_ASSERT_EQUAL(classOffset(18), offsetof(struct 
_LibreOfficeKitClass, startURP));
     CPPUNIT_ASSERT_EQUAL(classOffset(19), offsetof(struct 
_LibreOfficeKitClass, stopURP));
+    CPPUNIT_ASSERT_EQUAL(classOffset(20), offsetof(struct 
_LibreOfficeKitClass, joinThreads));
 
     // When extending LibreOfficeKit with a new function pointer,  add new 
assert for the offsetof the
     // new function pointer and bump this assert for the size of the class.
-    CPPUNIT_ASSERT_EQUAL(classOffset(20), sizeof(struct _LibreOfficeKitClass));
+    CPPUNIT_ASSERT_EQUAL(classOffset(21), sizeof(struct _LibreOfficeKitClass));
 
     CPPUNIT_ASSERT_EQUAL(documentClassOffset(0), offsetof(struct 
_LibreOfficeKitDocumentClass, destroy));
     CPPUNIT_ASSERT_EQUAL(documentClassOffset(1), offsetof(struct 
_LibreOfficeKitDocumentClass, saveAs));
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 0fd3e62a571c..3b97df3faa1c 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -2581,6 +2581,8 @@ lo_startURP(LibreOfficeKit* pThis, void* 
pReceiveURPFromLOContext, void* pSendUR
 
 static void lo_stopURP(LibreOfficeKit* pThis, void* pSendURPToLOContext);
 
+static int lo_joinThreads(LibreOfficeKit* pThis);
+
 static void lo_runLoop(LibreOfficeKit* pThis,
                        LibreOfficeKitPollCallback pPollCallback,
                        LibreOfficeKitWakeCallback pWakeCallback,
@@ -2625,6 +2627,7 @@ LibLibreOffice_Impl::LibLibreOffice_Impl()
         m_pOfficeClass->trimMemory = lo_trimMemory;
         m_pOfficeClass->startURP = lo_startURP;
         m_pOfficeClass->stopURP = lo_stopURP;
+        m_pOfficeClass->joinThreads = lo_joinThreads;
 
         gOfficeClass = m_pOfficeClass;
     }
@@ -3357,6 +3360,26 @@ static void lo_stopURP(LibreOfficeKit* /* pThis */,
     
static_cast<FunctionBasedURPConnection*>(pFunctionBasedURPConnection)->close();
 }
 
+
+static int lo_joinThreads(LibreOfficeKit* /* pThis */)
+{
+    comphelper::ThreadPool &pool = 
comphelper::ThreadPool::getSharedOptimalPool();
+    pool.joinThreadsIfIdle();
+
+//    if (comphelper::getWorkerCount() > 0)
+//        return 0;
+
+    // Grammar checker thread
+    css::uno::Reference<css::linguistic2::XLinguServiceManager2> xLangSrv =
+        css::linguistic2::LinguServiceManager::create(xContext);
+
+    auto joinable = dynamic_cast<comphelper::LibreOfficeKit::ThreadJoinable 
*>(xLangSrv.get());
+    if (joinable && !joinable->joinThreads())
+        return 0;
+
+    return 1;
+}
+
 static void lo_registerCallback (LibreOfficeKit* pThis,
                                  LibreOfficeKitCallback pCallback,
                                  void* pData)
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h 
b/include/LibreOfficeKit/LibreOfficeKit.h
index ed7f4e7f2d28..d924c416eb0b 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -140,6 +140,9 @@ struct _LibreOfficeKitClass
 
     /// @see lok::Office::stopURP
     void (*stopURP)(LibreOfficeKit* pThis, void* pSendURPToLOContext);
+
+    /// @see lok::Office::joinThreads
+    int (*joinThreads)(LibreOfficeKit* pThis);
 };
 
 #define LIBREOFFICEKIT_DOCUMENT_HAS(pDoc,member) 
LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitDocumentClass,member,(pDoc)->pClass->nSize)
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx 
b/include/LibreOfficeKit/LibreOfficeKit.hxx
index 6f75eb6be5cb..797dd6bca73b 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -1051,7 +1051,6 @@ public:
      * @since LibreOffice 6.0
      * @param pURL macro url to run
      */
-
     bool runMacro( const char* pURL)
     {
         return mpThis->pClass->runMacro( mpThis, pURL );
@@ -1197,6 +1196,17 @@ public:
     {
         mpThis->pClass->stopURP(mpThis, pURPContext);
     }
+
+    /**
+     * Joins all threads if possible to get down to a single process
+     * which can be forked from safely.
+     *
+     * @returns non-zero for successful join, 0 for failure.
+     */
+    int joinThreads()
+    {
+        return mpThis->pClass->joinThreads(mpThis);
+    }
 };
 
 /// Factory method to create a lok::Office instance.
diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx
index 545136f762ea..4ca03f049225 100644
--- a/include/comphelper/lok.hxx
+++ b/include/comphelper/lok.hxx
@@ -20,6 +20,14 @@ class LanguageTag;
 
 namespace comphelper::LibreOfficeKit
 {
+/// interface for allowing threads to be transiently shutdown.
+class COMPHELPER_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") ThreadJoinable
+{
+public:
+    /// shutdown and join threads, @returns true on success
+    virtual bool joinThreads() = 0;
+};
+
 // Functions to be called only from the LibreOfficeKit implementation in 
desktop, not from other
 // places in LibreOffice code.
 
diff --git a/linguistic/source/gciterator.cxx b/linguistic/source/gciterator.cxx
index b35882785995..ad85bab95953 100644
--- a/linguistic/source/gciterator.cxx
+++ b/linguistic/source/gciterator.cxx
@@ -312,6 +312,14 @@ void GrammarCheckingIterator::TerminateThread()
     }
 }
 
+
+bool GrammarCheckingIterator::joinThreads()
+{
+    TerminateThread();
+    return true;
+}
+
+
 sal_Int32 GrammarCheckingIterator::NextDocId()
 {
     ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() );
diff --git a/linguistic/source/gciterator.hxx b/linguistic/source/gciterator.hxx
index e25b15a96226..62b3a53af8fa 100644
--- a/linguistic/source/gciterator.hxx
+++ b/linguistic/source/gciterator.hxx
@@ -34,6 +34,7 @@
 #include <osl/thread.h>
 
 #include <com/sun/star/uno/Any.hxx>
+#include <comphelper/lok.hxx>
 #include <comphelper/interfacecontainer3.hxx>
 #include <i18nlangtag/lang.h>
 
@@ -80,7 +81,8 @@ class GrammarCheckingIterator:
         css::lang::XComponent,
         css::lang::XServiceInfo
     >,
-    public LinguDispatcher
+    public LinguDispatcher,
+    public comphelper::LibreOfficeKit::ThreadJoinable
 {
     //the queue is keeping track of all sentences to be checked
     //every element of this queue is a FlatParagraphEntry struct-object
@@ -185,6 +187,9 @@ public:
     // LinguDispatcher
     virtual void SetServiceList( const css::lang::Locale &rLocale, const 
css::uno::Sequence< OUString > &rSvcImplNames ) override;
     virtual css::uno::Sequence< OUString > GetServiceList( const 
css::lang::Locale &rLocale ) const override;
+
+    // comphelper::LibreOfficeKit::ThreadJoinable
+    virtual bool joinThreads() override;
 };
 
 
diff --git a/linguistic/source/lngsvcmgr.cxx b/linguistic/source/lngsvcmgr.cxx
index 850d4d813bfd..11b5440da5d4 100644
--- a/linguistic/source/lngsvcmgr.cxx
+++ b/linguistic/source/lngsvcmgr.cxx
@@ -452,6 +452,14 @@ void LngSvcMgr::modified(const lang::EventObject&)
     aUpdateIdle.Start();
 }
 
+bool LngSvcMgr::joinThreads()
+{
+    if (mxGrammarDsp && !
+        mxGrammarDsp->joinThreads())
+        return false;
+    return true;
+}
+
 //run update, and inform everyone that dictionaries (may) have changed, this
 //needs to be run in the main thread because
 //utl::ConfigChangeListener_Impl::changesOccurred grabs the SolarMutex and we
diff --git a/linguistic/source/lngsvcmgr.hxx b/linguistic/source/lngsvcmgr.hxx
index f21dc70a1b8c..fcec04f37237 100644
--- a/linguistic/source/lngsvcmgr.hxx
+++ b/linguistic/source/lngsvcmgr.hxx
@@ -22,6 +22,7 @@
 #include <cppuhelper/implbase.hxx>
 #include <comphelper/interfacecontainer3.hxx>
 
+#include <comphelper/lok.hxx>
 
 #include <com/sun/star/uno/Reference.h>
 #include <com/sun/star/lang/XServiceInfo.hpp>
@@ -58,7 +59,8 @@ class LngSvcMgr :
         css::lang::XServiceInfo,
         css::util::XModifyListener
     >,
-    private utl::ConfigItem
+    private utl::ConfigItem,
+    public comphelper::LibreOfficeKit::ThreadJoinable
 {
     friend class LngSvcMgrListenerHelper;
 
@@ -156,6 +158,9 @@ public:
     // XModifyListener
     virtual void SAL_CALL modified( const css::lang::EventObject& rEvent ) 
override;
 
+    // comphelper::LibreOfficeKit::ThreadJoinable
+    virtual bool joinThreads() override;
+
     bool    AddLngSvcEvtBroadcaster(
                 const css::uno::Reference< 
css::linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster );
 };

Reply via email to