vcl/source/treelist/transfer.cxx |   46 +++++++++++++--------------------------
 1 file changed, 16 insertions(+), 30 deletions(-)

New commits:
commit 2bde39767ff2aead9d4cfddc37f32103bfc52f63
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Dec 4 13:40:04 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Dec 5 05:40:32 2023 +0100

    Drop own mutex to prevent lock order problem
    
    When running UITests on Windows with parallelism, I often see deadlocks
    in clipboard threads, where one thread holds own mutex and tries to lock
    solar mutex, and the other holds it and waits for own mutex. The problem
    is in TransferableDataHelper::GetAny, where solar mutex is released
    temporarily.
    
    Avoid it by dropping own mutex, and only using solar mutex.
    
    Change-Id: Idbfa2e1399fe94d092b4090e7aa4956be4103744
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160296
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/vcl/source/treelist/transfer.cxx b/vcl/source/treelist/transfer.cxx
index 955b47b7cdf2..7e6009de77dc 100644
--- a/vcl/source/treelist/transfer.cxx
+++ b/vcl/source/treelist/transfer.cxx
@@ -23,7 +23,6 @@
 #include <shlobj.h>
 #endif
 #include <o3tl/char16_t2wchar_t.hxx>
-#include <osl/mutex.hxx>
 #include <rtl/uri.hxx>
 #include <sal/log.hxx>
 #include <tools/debug.hxx>
@@ -1036,7 +1035,6 @@ namespace {
 class TransferableClipboardNotifier : public ::cppu::WeakImplHelper< 
XClipboardListener >
 {
 private:
-    ::osl::Mutex&                   mrMutex;
     Reference< XClipboardNotifier > mxNotifier;
     TransferableDataHelper*         mpListener;
 
@@ -1048,7 +1046,7 @@ protected:
     virtual void SAL_CALL disposing( const EventObject& Source ) override;
 
 public:
-    TransferableClipboardNotifier( const Reference< XClipboard >& 
_rxClipboard, TransferableDataHelper& _rListener, ::osl::Mutex& _rMutex );
+    TransferableClipboardNotifier( const Reference< XClipboard >& 
_rxClipboard, TransferableDataHelper& _rListener );
 
     /// determines whether we're currently listening
     bool isListening() const { return mpListener != nullptr; }
@@ -1059,9 +1057,8 @@ public:
 
 }
 
-TransferableClipboardNotifier::TransferableClipboardNotifier( const Reference< 
XClipboard >& _rxClipboard, TransferableDataHelper& _rListener, ::osl::Mutex& 
_rMutex )
-    :mrMutex( _rMutex )
-    ,mxNotifier( _rxClipboard, UNO_QUERY )
+TransferableClipboardNotifier::TransferableClipboardNotifier( const Reference< 
XClipboard >& _rxClipboard, TransferableDataHelper& _rListener )
+    :mxNotifier( _rxClipboard, UNO_QUERY )
     ,mpListener( &_rListener )
 {
     osl_atomic_increment( &m_refCount );
@@ -1079,11 +1076,6 @@ 
TransferableClipboardNotifier::TransferableClipboardNotifier( const Reference< X
 void SAL_CALL TransferableClipboardNotifier::changedContents( const 
clipboard::ClipboardEvent& event )
 {
     SolarMutexGuard aSolarGuard;
-        // the SolarMutex here is necessary, since
-        // - we cannot call mpListener without our own mutex locked
-        // - Rebind respectively InitFormats (called by Rebind) will
-        // try to lock the SolarMutex, too
-    ::osl::MutexGuard aGuard( mrMutex );
     if( mpListener )
         mpListener->Rebind( event.Contents );
 }
@@ -1098,7 +1090,7 @@ void SAL_CALL TransferableClipboardNotifier::disposing( 
const EventObject& )
 
 void TransferableClipboardNotifier::dispose()
 {
-    ::osl::MutexGuard aGuard( mrMutex );
+    SolarMutexGuard g;
 
     Reference< XClipboardListener > xKeepMeAlive( this );
 
@@ -1111,7 +1103,6 @@ void TransferableClipboardNotifier::dispose()
 
 struct TransferableDataHelper_Impl
 {
-    ::osl::Mutex                    maMutex;
     rtl::Reference<TransferableClipboardNotifier>  mxClipboardListener;
 
     TransferableDataHelper_Impl()
@@ -1155,7 +1146,7 @@ TransferableDataHelper& 
TransferableDataHelper::operator=( const TransferableDat
 {
     if ( this != &rDataHelper )
     {
-        ::osl::MutexGuard aGuard(mxImpl->maMutex);
+        SolarMutexGuard g;
 
         const bool bWasClipboardListening = mxImpl->mxClipboardListener.is();
 
@@ -1176,7 +1167,7 @@ TransferableDataHelper& 
TransferableDataHelper::operator=( const TransferableDat
 
 TransferableDataHelper& 
TransferableDataHelper::operator=(TransferableDataHelper&& rDataHelper)
 {
-    ::osl::MutexGuard aGuard(mxImpl->maMutex);
+    SolarMutexGuard g;
 
     const bool bWasClipboardListening = mxImpl->mxClipboardListener.is();
 
@@ -1198,7 +1189,7 @@ TransferableDataHelper::~TransferableDataHelper()
 {
     StopClipboardListening( );
     {
-        ::osl::MutexGuard aGuard(mxImpl->maMutex);
+        SolarMutexGuard g;
         maFormats.clear();
         mxObjDesc.reset();
     }
@@ -1302,7 +1293,6 @@ void TransferableDataHelper::FillDataFlavorExVector( 
const Sequence< DataFlavor
 void TransferableDataHelper::InitFormats()
 {
     SolarMutexGuard aSolarGuard;
-    ::osl::MutexGuard aGuard(mxImpl->maMutex);
 
     maFormats.clear();
     mxObjDesc.reset(new TransferableObjectDescriptor);
@@ -1328,14 +1318,14 @@ void TransferableDataHelper::InitFormats()
 
 bool TransferableDataHelper::HasFormat( SotClipboardFormatId nFormat ) const
 {
-    ::osl::MutexGuard aGuard(mxImpl->maMutex);
+    SolarMutexGuard g;
     return std::any_of(maFormats.begin(), maFormats.end(),
               [&](const DataFlavorEx& data) { return data.mnSotId == nFormat; 
});
 }
 
 bool TransferableDataHelper::HasFormat( const DataFlavor& rFlavor ) const
 {
-    ::osl::MutexGuard aGuard(mxImpl->maMutex);
+    SolarMutexGuard g;
     for (auto const& format : maFormats)
     {
         if( TransferableDataHelper::IsEqual( rFlavor, format ) )
@@ -1347,20 +1337,20 @@ bool TransferableDataHelper::HasFormat( const 
DataFlavor& rFlavor ) const
 
 sal_uInt32 TransferableDataHelper::GetFormatCount() const
 {
-    ::osl::MutexGuard aGuard(mxImpl->maMutex);
+    SolarMutexGuard g;
     return maFormats.size();
 }
 
 SotClipboardFormatId TransferableDataHelper::GetFormat( sal_uInt32 nFormat ) 
const
 {
-    ::osl::MutexGuard aGuard(mxImpl->maMutex);
+    SolarMutexGuard g;
     DBG_ASSERT(nFormat < maFormats.size(), "TransferableDataHelper::GetFormat: 
invalid format index");
     return( ( nFormat < maFormats.size() ) ? maFormats[ nFormat ].mnSotId : 
SotClipboardFormatId::NONE );
 }
 
 DataFlavor TransferableDataHelper::GetFormatDataFlavor( sal_uInt32 nFormat ) 
const
 {
-    ::osl::MutexGuard aGuard(mxImpl->maMutex);
+    SolarMutexGuard g;
     DBG_ASSERT(nFormat < maFormats.size(), "TransferableDataHelper::GetFormat: 
invalid format index");
 
     DataFlavor aRet;
@@ -1409,11 +1399,11 @@ Any TransferableDataHelper::GetAny( 
SotClipboardFormatId nFormat, const OUString
 
 Any TransferableDataHelper::GetAny( const DataFlavor& rFlavor, const OUString& 
rDestDoc ) const
 {
-    ::osl::MutexGuard aGuard(mxImpl->maMutex);
     Any aRet;
 
     try
     {
+        SolarMutexGuard g;
         if( mxTransfer.is() )
         {
             const SotClipboardFormatId         nRequestFormat = 
SotExchange::GetFormat( rFlavor );
@@ -1429,8 +1419,6 @@ Any TransferableDataHelper::GetAny( const DataFlavor& 
rFlavor, const OUString& r
                     {
 // tdf#133365: only release solar mutex on Windows
 #ifdef _WIN32
-                        // tdf#133527: first, make sure that we actually hold 
the mutex
-                        SolarMutexGuard g;
                         // Our own thread may handle the nested 
IDataObject::GetData call,
                         // and try to acquire solar mutex
                         SolarMutexReleaser r;
@@ -1451,8 +1439,6 @@ Any TransferableDataHelper::GetAny( const DataFlavor& 
rFlavor, const OUString& r
             {
 // tdf#133365: only release solar mutex on Windows
 #ifdef _WIN32
-                // tdf#133527: first, make sure that we actually hold the mutex
-                SolarMutexGuard g;
                 // Our own thread may handle the nested IDataObject::GetData 
call,
                 // and try to acquire solar mutex
                 SolarMutexReleaser r;
@@ -2116,18 +2102,18 @@ void TransferableDataHelper::Rebind( const Reference< 
XTransferable >& _rxNewCon
 
 bool TransferableDataHelper::StartClipboardListening( )
 {
-    ::osl::MutexGuard aGuard(mxImpl->maMutex);
+    SolarMutexGuard g;
 
     StopClipboardListening( );
 
-    mxImpl->mxClipboardListener = new 
TransferableClipboardNotifier(mxClipboard, *this, mxImpl->maMutex);
+    mxImpl->mxClipboardListener = new 
TransferableClipboardNotifier(mxClipboard, *this);
 
     return mxImpl->mxClipboardListener->isListening();
 }
 
 void TransferableDataHelper::StopClipboardListening( )
 {
-    ::osl::MutexGuard aGuard(mxImpl->maMutex);
+    SolarMutexGuard g;
 
     if (mxImpl->mxClipboardListener.is())
     {

Reply via email to