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.bergmann@allotropia.de>
This commit is contained in:
Stephan Bergmann 2024-08-16 15:02:15 +02:00
parent 38b9d5e86d
commit 50cd19debb
10 changed files with 49 additions and 5 deletions

View file

@ -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();
};
}; }; };

View file

@ -19,6 +19,8 @@ $(eval $(call gb_Library_use_libraries,embindtest, \
cppu \
cppuhelper \
sal \
salhelper \
vcl \
))
$(eval $(call gb_Library_use_sdk_api,embindtest))

View file

@ -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""_ustr;
};

View file

@ -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)]);

View file

@ -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

View file

@ -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;
}

View file

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

View file

@ -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 )

View file

@ -624,7 +624,7 @@ void DeInitVCL()
// Deinit Sal
if (pSVData->mpDefInst)
{
pSVData->mpDefInst->ReleaseYieldMutexAll();
pSVData->mpDefInst->ReleaseYieldMutex(true);
DestroySalInstance( pSVData->mpDefInst );
pSVData->mpDefInst = nullptr;
}

View file

@ -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,