embeddedobj/source/msole/olecomponent.cxx    |   42 ++++++++++-----------------
 fpicker/source/win32/VistaFilePickerImpl.cxx |    1 
 include/vcl/svapp.hxx                        |   12 ++++++-
 sfx2/source/control/bindings.cxx             |    1 
 vcl/source/app/scheduler.cxx                 |    7 ++--
 vcl/source/helper/threadex.cxx               |    1 
 vcl/win/dtrans/MtaOleClipb.cxx               |   35 +++++++++++++---------
 vcl/win/dtrans/WinClipboard.cxx              |   14 +++++----
 8 files changed, 62 insertions(+), 51 deletions(-)

New commits:
commit cb9c9d990600baad9e5a63c80ddaa46e98248161
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Mar 21 10:01:36 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Mar 27 09:36:54 2024 +0500

    Downgrade sfx::SfxBindings aAutoTimer to an idle
    
    This is a follow-up to commit f45402ae3f5241b460d9f1dcb04183893e1f91f7
    (Fix a spurious JunitTest_sw_unoapi_3 failure, 2024-03-15). As noted
    by Stephan, the failure persisted; it was because the update of slots
    also accessed the changing document model, and it wasn't prevented by
    IdlesLockGuard, because aAutoTimer had a default priority.
    
    Change-Id: Iad8dfadcd35d9611e61e4c011511d6155a343f58
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165090
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sfx2/source/control/bindings.cxx b/sfx2/source/control/bindings.cxx
index 4ea06231562a..44fbbd10c2f0 100644
--- a/sfx2/source/control/bindings.cxx
+++ b/sfx2/source/control/bindings.cxx
@@ -146,6 +146,7 @@ SfxBindings::SfxBindings()
 
     // all caches are valid (no pending invalidate-job)
     // create the list of caches
+    pImpl->aAutoTimer.SetPriority(TaskPriority::HIGH_IDLE);
     pImpl->aAutoTimer.SetInvokeHandler( LINK(this, SfxBindings, NextJob) );
 }
 
commit 3bb1590c78ffcf26cfadcc89a3dd3e0bf8be50e3
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Mar 21 10:00:44 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Mar 27 09:27:14 2024 +0500

    Only hold clipboard mutexes to obtain the values, to avoid deadlocks
    
    Change-Id: I36a2f6e444b8a5397b96d3cba475a8d06ea86459
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165089
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/vcl/win/dtrans/MtaOleClipb.cxx b/vcl/win/dtrans/MtaOleClipb.cxx
index 865025057dcc..19a37dc52e19 100644
--- a/vcl/win/dtrans/MtaOleClipb.cxx
+++ b/vcl/win/dtrans/MtaOleClipb.cxx
@@ -713,25 +713,32 @@ DWORD WINAPI 
CMtaOleClipboard::clipboardChangedNotifierThreadProc( _In_ LPVOID p
         MsgWaitForMultipleObjects(2, pInst->m_hClipboardChangedNotifierEvents, 
false, INFINITE,
                                   QS_ALLINPUT | QS_ALLPOSTMESSAGE);
 
-        ClearableMutexGuard aGuard2( pInst->m_ClipboardChangedEventCountMutex 
);
-
-        if ( pInst->m_ClipboardChangedEventCount > 0 )
+        bool hadEvents;
         {
-            pInst->m_ClipboardChangedEventCount--;
-            if ( 0 == pInst->m_ClipboardChangedEventCount )
-                ResetEvent( pInst->m_hClipboardChangedEvent );
-
-            aGuard2.clear( );
+            ClearableMutexGuard 
aGuard2(pInst->m_ClipboardChangedEventCountMutex);
+            hadEvents = pInst->m_ClipboardChangedEventCount > 0;
+            if (hadEvents)
+            {
+                pInst->m_ClipboardChangedEventCount--;
+                if (0 == pInst->m_ClipboardChangedEventCount)
+                    ResetEvent(pInst->m_hClipboardChangedEvent);
+            }
+        }
 
-            // nobody should touch m_pfncClipViewerCallback while we do
-            MutexGuard aClipViewerGuard( pInst->m_pfncClipViewerCallbackMutex 
);
+        if (hadEvents)
+        {
+            LPFNC_CLIPVIEWER_CALLBACK_t pClipViewerCallback;
+            {
+                // nobody should touch m_pfncClipViewerCallback while we do
+                // but don't hold the mutex while calling the callback itself: 
it could deadlock
+                MutexGuard 
aClipViewerGuard(pInst->m_pfncClipViewerCallbackMutex);
+                pClipViewerCallback = pInst->m_pfncClipViewerCallback;
+            }
 
             // notify all clipboard listener
-            if ( pInst->m_pfncClipViewerCallback )
-                pInst->m_pfncClipViewerCallback( );
+            if (pClipViewerCallback)
+                pClipViewerCallback();
         }
-        else
-            aGuard2.clear( );
     }
 
     return 0;
diff --git a/vcl/win/dtrans/WinClipboard.cxx b/vcl/win/dtrans/WinClipboard.cxx
index c2fa269dfc5d..33c8023a925c 100644
--- a/vcl/win/dtrans/WinClipboard.cxx
+++ b/vcl/win/dtrans/WinClipboard.cxx
@@ -373,13 +373,17 @@ void CWinClipboard::unregisterClipboardViewer() { 
m_MtaOleClipboard.registerClip
 
 void WINAPI CWinClipboard::onClipboardContentChanged()
 {
-    osl::MutexGuard aGuard(s_aClipboardSingletonMutex);
+    rtl::Reference<CWinClipboard> pWinClipboard;
+    {
+        // Only hold the mutex to obtain a safe reference to the impl, to 
avoid deadlock
+        osl::MutexGuard aGuard(s_aClipboardSingletonMutex);
+        pWinClipboard.set(s_pCWinClipbImpl);
+    }
 
-    // reassociation to instance through static member
-    if (nullptr != s_pCWinClipbImpl)
+    if (pWinClipboard)
     {
-        s_pCWinClipbImpl->m_foreignContent.clear();
-        s_pCWinClipbImpl->notifyAllClipboardListener();
+        pWinClipboard->m_foreignContent.clear();
+        pWinClipboard->notifyAllClipboardListener();
     }
 }
 
commit 1d43c9ad8485ca837767bff87160639c65932e6c
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Mar 26 12:11:13 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Mar 27 09:05:39 2024 +0500

    This assert was wrong
    
    In commit e2bfc34d146806a8f96be0cd2323d716f12cba4e (Reimplement
    OleComponentNative_Impl to use IGlobalInterfaceTable, 2024-03-11),
    I added the assert in a false assumption that RunObject may only
    be called once. Indeed, this is not so. Thus just make sure to not
    try to register it second time.
    
    Change-Id: I36fc4f3939bd0061e462659749bba8e4bd3075ba
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165299
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/embeddedobj/source/msole/olecomponent.cxx 
b/embeddedobj/source/msole/olecomponent.cxx
index 142d92ddf1c3..ca104a7c3425 100644
--- a/embeddedobj/source/msole/olecomponent.cxx
+++ b/embeddedobj/source/msole/olecomponent.cxx
@@ -200,7 +200,8 @@ private:
 
     template <typename T> void registerInterface(T* pInterface, DWORD& cookie)
     {
-        assert(cookie == 0); // do not set again
+        if (cookie != 0) // E.g., on subsequent RunObject calls
+            return;
         HRESULT hr = m_pGlobalTable->RegisterInterfaceInGlobal(pInterface, 
__uuidof(T), &cookie);
         SAL_WARN_IF(FAILED(hr), "embeddedobj.ole", "RegisterInterfaceInGlobal 
failed");
     }
commit 8e47b628cc7a1d6496a5f73748ab5e7b441fdb1d
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Mar 26 19:06:25 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Mar 26 23:19:44 2024 +0500

    Set the condition, even when main thread message queue is empty
    
    Post an empty user event for that.
    
    Change-Id: I9ab4b4374a25eddce8c58d36f58e08bec4a1855c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165352
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 61b82d21b984..f7075584924b 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -285,6 +285,9 @@ Scheduler::IdlesLockGuard::IdlesLockGuard()
         // condition to proceed. Only main thread returning to 
Application::Execute guarantees that
         // the flag really took effect.
         pSVData->m_inExecuteCondtion.reset();
+        // Put an empty event to the application's queue, to make sure that it 
loops through the
+        // code that sets the condition, even when there's no other events in 
the queue
+        Application::PostUserEvent({});
         SolarMutexReleaser releaser;
         pSVData->m_inExecuteCondtion.wait();
     }
commit 51b7d8314a377249b99643b5174b3a5ca71ffde5
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Mar 25 09:05:00 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Mar 26 23:19:38 2024 +0500

    Relax SolarMutexReleaser precondition to not require SolarMutex lock
    
    As discussed on 
https://gerrit.libreoffice.org/c/core/+/164843/2#message-8873d3d119de7206b33bc824f5809b8b1d3d97da,
    it is impossible at times to know in advance, if a specific code, that
    must not be guarded by SolarMutex (e.g., calling to other threads, which
    might need to grab the mutex), will itself be guarded by SolarMutex.
    Before this change, a required pre-requisite for SolarMutexReleaser use
    was existing lock of SolarMutex; otherwise, an attempt to release it
    would call abort(). Thus, in some places we had to grab the mutex prior
    to releasing it, and that itself introduced more potential for deadlock.
    
    Now the SolarMutexReleaser is safe to use without the lock, in which
    case, it will do nothing.
    
    Change-Id: I8759c2f6ed448598b3be4d6c5109804b5e7523ed
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165262
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/embeddedobj/source/msole/olecomponent.cxx 
b/embeddedobj/source/msole/olecomponent.cxx
index da10b9d9d233..142d92ddf1c3 100644
--- a/embeddedobj/source/msole/olecomponent.cxx
+++ b/embeddedobj/source/msole/olecomponent.cxx
@@ -206,15 +206,6 @@ private:
     }
 };
 
-namespace
-{
-struct SafeSolarMutexReleaser
-{
-    SolarMutexGuard guard; // To make sure we actually hold it prior to release
-    SolarMutexReleaser releaser;
-};
-}
-
 static DWORD GetAspectFromFlavor( const datatransfer::DataFlavor& aFlavor )
 {
     if ( aFlavor.MimeType.indexOf( ";Aspect=THUMBNAIL" ) != -1 )
@@ -569,7 +560,7 @@ void OleComponent::RetrieveObjectDataFlavors_Impl()
             HRESULT hr;
             sal::systools::COMReference< IEnumFORMATETC > pFormatEnum;
             {
-                SafeSolarMutexReleaser releaser;
+                SolarMutexReleaser releaser;
                 hr = pDataObject->EnumFormatEtc(DATADIR_GET, &pFormatEnum);
             }
             if ( SUCCEEDED( hr ) && pFormatEnum )
@@ -859,7 +850,7 @@ void OleComponent::InitEmbeddedCopyOfLink( 
rtl::Reference<OleComponent> const &
     // the object must be already disconnected from the temporary URL
     auto pStorage(m_pNativeImpl->CreateNewStorage(getTempURL()));
 
-    SafeSolarMutexReleaser releaser;
+    SolarMutexReleaser releaser;
 
     auto 
pDataObject(pOleLinkComponentObj.QueryInterface<IDataObject>(sal::systools::COM_QUERY));
     if ( pDataObject && SUCCEEDED( OleQueryCreateFromData( pDataObject ) ) )
@@ -987,7 +978,7 @@ void OleComponent::CloseObject()
     auto pOleObject(m_pNativeImpl->get<IOleObject>());
     if (pOleObject && OleIsRunning(pOleObject))
     {
-        SafeSolarMutexReleaser releaser;
+        SolarMutexReleaser releaser;
         HRESULT hr = pOleObject->Close(OLECLOSE_NOSAVE); // must be saved 
before
         SAL_WARN_IF(FAILED(hr), "embeddedobj.ole", "IOleObject::Close failed");
     }
@@ -1005,7 +996,7 @@ uno::Sequence< embed::VerbDescriptor > 
OleComponent::GetVerbList()
         sal::systools::COMReference< IEnumOLEVERB > pEnum;
         HRESULT hr;
         {
-            SafeSolarMutexReleaser releaser;
+            SolarMutexReleaser releaser;
             hr = pOleObject->EnumVerbs(&pEnum);
         }
         if (SUCCEEDED(hr))
@@ -1048,7 +1039,7 @@ void OleComponent::ExecuteVerb( sal_Int32 nVerbID )
     if (!pOleObject)
         throw embed::WrongStateException(); // TODO
 
-    SafeSolarMutexReleaser releaser;
+    SolarMutexReleaser releaser;
 
     // TODO: probably extents should be set here and stored in aRect
     // TODO: probably the parent window also should be set
@@ -1065,7 +1056,7 @@ void OleComponent::SetHostName( const OUString& 
aEmbDocName )
     if (!pOleObject)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
-    SafeSolarMutexReleaser releaser;
+    SolarMutexReleaser releaser;
     pOleObject->SetHostNames(L"app name", o3tl::toW(aEmbDocName.getStr()));
 }
 
@@ -1081,7 +1072,7 @@ void OleComponent::SetExtent( const awt::Size& 
aVisAreaSize, sal_Int64 nAspect )
     SIZEL aSize = { aVisAreaSize.Width, aVisAreaSize.Height };
     HRESULT hr;
     {
-        SafeSolarMutexReleaser releaser;
+        SolarMutexReleaser releaser;
         hr = pOleObject->SetExtent(nMSAspect, &aSize);
     }
 
@@ -1117,7 +1108,7 @@ awt::Size OleComponent::GetExtent( sal_Int64 nAspect )
 
             HRESULT hr;
             {
-                SafeSolarMutexReleaser releaser;
+                SolarMutexReleaser releaser;
                 hr = pDataObject->GetData(&aFormat, &aMedium);
             }
 
@@ -1204,7 +1195,7 @@ awt::Size OleComponent::GetCachedExtent( sal_Int64 
nAspect )
 
     HRESULT hr;
     {
-        SafeSolarMutexReleaser releaser;
+        SolarMutexReleaser releaser;
         hr = pViewObject2->GetExtent(nMSAspect, -1, nullptr, &aSize);
     }
 
@@ -1235,7 +1226,7 @@ awt::Size OleComponent::GetRecommendedExtent( sal_Int64 
nAspect )
     SIZEL aSize;
     HRESULT hr;
     {
-        SafeSolarMutexReleaser releaser;
+        SolarMutexReleaser releaser;
         hr = pOleObject->GetExtent(nMSAspect, &aSize);
     }
     if ( FAILED( hr ) )
@@ -1256,7 +1247,7 @@ sal_Int64 OleComponent::GetMiscStatus( sal_Int64 nAspect )
 
     DWORD nResult = 0;
     {
-        SafeSolarMutexReleaser releaser;
+        SolarMutexReleaser releaser;
         pOleObject->GetMiscStatus(static_cast<DWORD>(nAspect), &nResult);
     }
     return static_cast<sal_Int64>(nResult); // first 32 bits are for MS flags
@@ -1272,7 +1263,7 @@ uno::Sequence< sal_Int8 > OleComponent::GetCLSID()
     GUID aCLSID;
     HRESULT hr;
     {
-        SafeSolarMutexReleaser releaser;
+        SolarMutexReleaser releaser;
         hr = pOleObject->GetUserClassID(&aCLSID);
     }
     if ( FAILED( hr ) )
@@ -1295,7 +1286,7 @@ bool OleComponent::IsDirty()
     if ( !pPersistStorage )
         throw io::IOException(); // TODO
 
-    SafeSolarMutexReleaser releaser;
+    SolarMutexReleaser releaser;
     HRESULT hr = pPersistStorage->IsDirty();
     return ( hr != S_FALSE );
 }
@@ -1311,7 +1302,7 @@ void OleComponent::StoreOwnTmpIfNecessary()
     if ( !pPersistStorage )
         throw io::IOException(); // TODO
 
-    SafeSolarMutexReleaser releaser;
+    SolarMutexReleaser releaser;
 
     if ( m_bWorkaroundActive || pPersistStorage->IsDirty() != S_FALSE )
     {
@@ -1573,7 +1564,7 @@ uno::Any SAL_CALL OleComponent::getTransferData( const 
datatransfer::DataFlavor&
 
                 HRESULT hr;
                 {
-                    SafeSolarMutexReleaser releaser;
+                    SolarMutexReleaser releaser;
                     hr = pDataObject->GetData(&aFormat, &aMedium);
                 }
                 if ( SUCCEEDED( hr ) )
diff --git a/fpicker/source/win32/VistaFilePickerImpl.cxx 
b/fpicker/source/win32/VistaFilePickerImpl.cxx
index 741fdadb621a..d1a0cdf8a5a9 100644
--- a/fpicker/source/win32/VistaFilePickerImpl.cxx
+++ b/fpicker/source/win32/VistaFilePickerImpl.cxx
@@ -965,7 +965,6 @@ void VistaFilePickerImpl::impl_sta_ShowDialogModal(Request& 
rRequest)
     {
         // tdf#146007: Make sure we don't hold solar mutex: COM may need to 
forward
         // the execution to the main thread, and holding solar mutex could 
deadlock
-        SolarMutexGuard g; // First acquire, to avoid releaser failure
         SolarMutexReleaser r;
         // show dialog and wait for user decision
         hResult = iDialog->Show(m_hParentWindow ? m_hParentWindow
diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index 398358f1bfad..7aef4926f9c2 100644
--- a/include/vcl/svapp.hxx
+++ b/include/vcl/svapp.hxx
@@ -1448,8 +1448,16 @@ class SolarMutexReleaser
 {
     const sal_uInt32 mnReleased;
 public:
-    SolarMutexReleaser(): mnReleased(Application::ReleaseSolarMutex()) {}
-    ~SolarMutexReleaser() { Application::AcquireSolarMutex( mnReleased ); }
+    SolarMutexReleaser()
+        : mnReleased(
+            Application::GetSolarMutex().IsCurrentThread() ? 
Application::ReleaseSolarMutex() : 0)
+    {
+    }
+    ~SolarMutexReleaser()
+    {
+        if (mnReleased)
+            Application::AcquireSolarMutex(mnReleased);
+    }
 };
 
 VCL_DLLPUBLIC Application* GetpApp();
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index c0fc79d4ac5c..61b82d21b984 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -285,9 +285,7 @@ Scheduler::IdlesLockGuard::IdlesLockGuard()
         // condition to proceed. Only main thread returning to 
Application::Execute guarantees that
         // the flag really took effect.
         pSVData->m_inExecuteCondtion.reset();
-        std::optional<SolarMutexReleaser> releaser;
-        if (pSVData->mpDefInst->GetYieldMutex()->IsCurrentThread())
-            releaser.emplace();
+        SolarMutexReleaser releaser;
         pSVData->m_inExecuteCondtion.wait();
     }
 }
diff --git a/vcl/source/helper/threadex.cxx b/vcl/source/helper/threadex.cxx
index 1590b91f1167..cbd342bd28df 100644
--- a/vcl/source/helper/threadex.cxx
+++ b/vcl/source/helper/threadex.cxx
@@ -52,7 +52,6 @@ void SolarThreadExecutor::execute()
         m_aStart.reset();
         m_aFinish.reset();
         ImplSVEvent* nEvent = Application::PostUserEvent(LINK(this, 
SolarThreadExecutor, worker));
-        SolarMutexGuard aGuard;
         SolarMutexReleaser aReleaser;
         if (m_aStart.wait() == osl::Condition::result_timeout)
         {

Reply via email to