offapi/org/libreoffice/embindtest/XTest.idl |    1 
 unotest/Library_embindtest.mk               |    2 +
 unotest/source/embindtest/embindtest.cxx    |   29 ++++++++++++++++++++++++++++
 unotest/source/embindtest/embindtest.js     |    1 
 vcl/inc/salinst.hxx                         |    2 -
 vcl/qt5/QtInstance.cxx                      |   11 ++++++++++
 vcl/source/app/salvtables.cxx               |    2 -
 vcl/source/app/svapp.cxx                    |    2 -
 vcl/source/app/svmain.cxx                   |    2 -
 vcl/win/gdi/salprn.cxx                      |    2 -
 10 files changed, 49 insertions(+), 5 deletions(-)

New commits:
commit 50cd19debbd3f94df0fc4b370f6f6e69d4a1e085
Author:     Stephan Bergmann <stephan.bergm...@allotropia.de>
AuthorDate: Fri Aug 16 15:02:15 2024 +0200
Commit:     Stephan Bergmann <stephan.bergm...@allotropia.de>
CommitDate: Sun Aug 18 15:10:00 2024 +0200

    Emscripten: Clean up SolarMutex
    
    ...before disappearing through the QApplication::exec() hole, or else the
    SolarMutex would remain locked forever on the application's main thread.
    
    This requires changing SalInstance::ReleaseYieldMutexAll() to
    SalInstance::ReleaseYieldMutex(bool all).  (Further recursive locking of the
    SolarMutex via SolarMutexGuard instances that would be present on the call 
stack
    leading up to the call to QApplication::exec() would be released during the
    stack unwinding, so just undo the one acquiring done in InitVCL, not all of
    them.)
    
    Change-Id: I9ef57abb7da7f840999700e4eaeeefd2da784645
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171956
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <stephan.bergm...@allotropia.de>

diff --git a/offapi/org/libreoffice/embindtest/XTest.idl 
b/offapi/org/libreoffice/embindtest/XTest.idl
index 8d46c9e71d5a..276ce260a8e1 100644
--- a/offapi/org/libreoffice/embindtest/XTest.idl
+++ b/offapi/org/libreoffice/embindtest/XTest.idl
@@ -133,6 +133,7 @@ interface XTest {
     void passInterface([in] com::sun::star::uno::XInterface object);
     boolean checkAttributes([in] org::libreoffice::embindtest::XAttributes 
object);
     [attribute] string StringAttribute;
+    boolean testSolarMutex();
 };
 
 }; }; };
diff --git a/unotest/Library_embindtest.mk b/unotest/Library_embindtest.mk
index e71fedc069dd..be18ca4d792d 100644
--- a/unotest/Library_embindtest.mk
+++ b/unotest/Library_embindtest.mk
@@ -19,6 +19,8 @@ $(eval $(call gb_Library_use_libraries,embindtest, \
     cppu \
     cppuhelper \
     sal \
+    salhelper \
+    vcl \
 ))
 
 $(eval $(call gb_Library_use_sdk_api,embindtest))
diff --git a/unotest/source/embindtest/embindtest.cxx 
b/unotest/source/embindtest/embindtest.cxx
index 292c492a4478..60150dcd2ad9 100644
--- a/unotest/source/embindtest/embindtest.cxx
+++ b/unotest/source/embindtest/embindtest.cxx
@@ -35,10 +35,12 @@
 #include <org/libreoffice/embindtest/XTest.hpp>
 #include <rtl/ustring.hxx>
 #include <sal/types.h>
+#include <salhelper/thread.hxx>
 #include <uno/dispatcher.hxx>
 #include <uno/environment.h>
 #include <uno/environment.hxx>
 #include <uno/mapping.hxx>
+#include <vcl/svapp.hxx>
 
 namespace com::sun::star::uno
 {
@@ -47,6 +49,24 @@ class XComponentContext;
 
 namespace
 {
+class TestThread : public salhelper::Thread
+{
+public:
+    TestThread()
+        : Thread("embindtest")
+    {
+    }
+
+    bool value = false;
+
+private:
+    void execute() override
+    {
+        SolarMutexGuard g;
+        value = true;
+    }
+};
+
 class Test : public cppu::WeakImplHelper<org::libreoffice::embindtest::XTest>
 {
     sal_Bool SAL_CALL getBoolean() override { return true; }
@@ -871,6 +891,15 @@ class Test : public 
cppu::WeakImplHelper<org::libreoffice::embindtest::XTest>
 
     void SAL_CALL setStringAttribute(OUString const& value) override { 
stringAttribute_ = value; }
 
+    sal_Bool SAL_CALL testSolarMutex() override
+    {
+        TestThread t;
+        t.launch();
+        t.join();
+        SolarMutexGuard g;
+        return t.value;
+    }
+
     OUString stringAttribute_ = u"hä"_ustr;
 };
 
diff --git a/unotest/source/embindtest/embindtest.js 
b/unotest/source/embindtest/embindtest.js
index 2242e5f81a8f..f75653a897cf 100644
--- a/unotest/source/embindtest/embindtest.js
+++ b/unotest/source/embindtest/embindtest.js
@@ -901,6 +901,7 @@ Module.uno_init.then(function() {
     console.assert(test.StringAttribute === 'hä');
     test.StringAttribute = 'foo';
     console.assert(test.StringAttribute === 'foo');
+    console.assert(test.testSolarMutex());
 
     const args = new Module.uno_Sequence_any(
         [new 
Module.uno_Any(Module.uno_Type.Interface('com.sun.star.uno.XInterface'), 
test)]);
diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx
index 380ee2ce202e..1fbe86285054 100644
--- a/vcl/inc/salinst.hxx
+++ b/vcl/inc/salinst.hxx
@@ -137,7 +137,7 @@ public:
 
     // YieldMutex
     comphelper::SolarMutex* GetYieldMutex();
-    sal_uInt32              ReleaseYieldMutexAll();
+    sal_uInt32              ReleaseYieldMutex(bool all);
     void                    AcquireYieldMutex(sal_uInt32 nCount = 1);
 
     // return true, if the current thread is the main thread
diff --git a/vcl/qt5/QtInstance.cxx b/vcl/qt5/QtInstance.cxx
index 6872fb0fe1a3..dfcf0c2c4f08 100644
--- a/vcl/qt5/QtInstance.cxx
+++ b/vcl/qt5/QtInstance.cxx
@@ -55,6 +55,7 @@
 #include <vcl/stdtext.hxx>
 #include <vcl/sysdata.hxx>
 #include <sal/log.hxx>
+#include <o3tl/unreachable.hxx>
 #include <osl/process.h>
 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && ENABLE_GSTREAMER_1_0 && 
QT5_HAVE_GOBJECT
 #include <unx/gstsink.hxx>
@@ -769,7 +770,17 @@ bool QtInstance::DoExecute(int& nExitCode)
 {
     const bool bIsOnSystemEventLoop = Application::IsOnSystemEventLoop();
     if (bIsOnSystemEventLoop)
+    {
+#if defined EMSCRIPTEN
+        // For Emscripten, QApplication::exec() will unwind the stack by 
throwing a JavaScript
+        // exception, so we need to manually undo the call of 
AcquireYieldMutex() done in InitVCL:
+        ImplGetSVData()->mpDefInst->ReleaseYieldMutex(false);
+#endif
         nExitCode = QApplication::exec();
+#if defined EMSCRIPTEN
+        O3TL_UNREACHABLE;
+#endif
+    }
     return bIsOnSystemEventLoop;
 }
 
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 7e2a81f2cef4..7e18d15c470e 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -141,7 +141,7 @@ SalInstance::~SalInstance() {}
 
 comphelper::SolarMutex* SalInstance::GetYieldMutex() { return 
m_pYieldMutex.get(); }
 
-sal_uInt32 SalInstance::ReleaseYieldMutexAll() { return 
m_pYieldMutex->release(true); }
+sal_uInt32 SalInstance::ReleaseYieldMutex(bool all) { return 
m_pYieldMutex->release(all); }
 
 void SalInstance::AcquireYieldMutex(sal_uInt32 nCount) { 
m_pYieldMutex->acquire(nCount); }
 
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 458da9d8c251..debd5ec920ff 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -499,7 +499,7 @@ bool Application::IsMainThread()
 sal_uInt32 Application::ReleaseSolarMutex()
 {
     ImplSVData* pSVData = ImplGetSVData();
-    return pSVData->mpDefInst->ReleaseYieldMutexAll();
+    return pSVData->mpDefInst->ReleaseYieldMutex(true);
 }
 
 void Application::AcquireSolarMutex( sal_uInt32 nCount )
diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index f046755863f1..fd5ea7b3ef0b 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -624,7 +624,7 @@ void DeInitVCL()
     // Deinit Sal
     if (pSVData->mpDefInst)
     {
-        pSVData->mpDefInst->ReleaseYieldMutexAll();
+        pSVData->mpDefInst->ReleaseYieldMutex(true);
         DestroySalInstance( pSVData->mpDefInst );
         pSVData->mpDefInst = nullptr;
     }
diff --git a/vcl/win/gdi/salprn.cxx b/vcl/win/gdi/salprn.cxx
index b43c59e27473..393c8c7b1f3a 100644
--- a/vcl/win/gdi/salprn.cxx
+++ b/vcl/win/gdi/salprn.cxx
@@ -382,7 +382,7 @@ static bool ImplUpdateSalJobSetup( WinSalInfoPrinter const 
* pPrinter, ImplJobSe
     sal_uInt32 nMutexCount = 0;
     WinSalInstance* pInst = GetSalData()->mpInstance;
     if ( pInst && pVisibleDlgParent )
-        nMutexCount = pInst->ReleaseYieldMutexAll();
+        nMutexCount = pInst->ReleaseYieldMutex(true);
 
     BYTE* pOutDevMode = reinterpret_cast<BYTE*>(pOutBuffer) + 
pOutBuffer->mnDriverOffset;
     nRet = DocumentPropertiesW( hWnd, hPrn,

Reply via email to