[Libreoffice-commits] core.git: dtrans/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Tue Feb 5 09:09:39 UTC 2019


 dtrans/source/win32/clipb/MtaOleClipb.cxx |  102 ++++++++++++++++++++++++++----
 dtrans/source/win32/clipb/MtaOleClipb.hxx |    1 
 2 files changed, 90 insertions(+), 13 deletions(-)

New commits:
commit 11a2809e369b2a6fcbb2d7f0db131a945557c6e2
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Mon Feb 4 23:12:42 2019 +0300
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Tue Feb 5 10:09:16 2019 +0100

    tdf#122435: reimplement fix for tdf#109085
    
    This reverts commit 3d8c159841bcab7365b2bed3df71ed3c15188312, and
    instead, checks if the MtaOleReq window is not destroyed yet, in
    addition to the wait for the condition. This allows to avoid wait
    forever for condition which never gets signalled, and process the
    sent messages when waiting.
    
    The window's WM_DESTROY handler sets the event signalling that.
    The Win32Condition's wait() is changed to take the abort event,
    and return true if its own event fired, and false if abort event
    fired.
    
    Change-Id: I1861dd3dabb39329976a3ccf2a5392c9ddbf9613
    Reviewed-on: https://gerrit.libreoffice.org/67383
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/dtrans/source/win32/clipb/MtaOleClipb.cxx b/dtrans/source/win32/clipb/MtaOleClipb.cxx
index 02a5f309aa14..ac3dc68083e1 100644
--- a/dtrans/source/win32/clipb/MtaOleClipb.cxx
+++ b/dtrans/source/win32/clipb/MtaOleClipb.cxx
@@ -62,11 +62,72 @@ namespace /* private */
     const sal_uInt32 MAX_WAITTIME                   = 10000;  // msec
     const sal_uInt32 MAX_WAIT_SHUTDOWN              = 10000; // msec
 
-    const bool MANUAL_RESET                     = true;
-    const bool INIT_NONSIGNALED                 = false;
+    const BOOL MANUAL_RESET = TRUE;
+    const BOOL INIT_NONSIGNALED = FALSE;
+
+    /*  Cannot use osl conditions because they are blocking
+        without waking up on messages sent by another thread
+        this leads to deadlocks because we are blocking the
+        communication between inter-thread marshalled COM
+        pointers.
+        COM Proxy-Stub communication uses SendMessages for
+        synchronization purposes.
+    */
+    class Win32Condition
+    {
+    public:
+        Win32Condition() = default;
+
+        ~Win32Condition() { CloseHandle(m_hEvent); }
+
+        // wait infinite for own event (or abort event) be signaled
+        // leave messages sent through
+        bool wait(HANDLE hEvtAbort)
+        {
+            const HANDLE hWaitArray[2] = { m_hEvent, hEvtAbort };
+            while (true)
+            {
+                DWORD dwResult
+                    = MsgWaitForMultipleObjects(2, hWaitArray, FALSE, INFINITE, QS_SENDMESSAGE);
+
+                switch (dwResult)
+                {
+                    case WAIT_OBJECT_0: // wait successful
+                        return true;
+
+                    case WAIT_OBJECT_0 + 1: // wait aborted
+                        return false;
+
+                    case WAIT_OBJECT_0 + 2:
+                    {
+                        /* PeekMessage processes all messages in the SendMessage
+                           queue that's what we want, messages from the PostMessage
+                           queue stay untouched */
+                        MSG msg;
+                        PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE);
+
+                        break;
+                    }
+                }
+            }
+        }
+
+        // set the event
+        void set() { SetEvent(m_hEvent); }
+
+    private:
+        HANDLE m_hEvent = CreateEventW(nullptr, MANUAL_RESET, INIT_NONSIGNALED, nullptr);
+
+        // prevent copy/assignment
+        Win32Condition(const Win32Condition&) = delete;
+        Win32Condition& operator=(const Win32Condition&) = delete;
+    };
+
+    // we use one condition for every request
 
     struct MsgCtx
     {
+        Win32Condition  aCondition;
         HRESULT         hr;
     };
 
@@ -159,6 +220,8 @@ CMtaOleClipboard::CMtaOleClipboard( ) :
     m_uOleThreadId( 0 ),
     m_hEvtThrdReady( nullptr ),
     m_hwndMtaOleReqWnd( nullptr ),
+    // signals that the window is destroyed - to stop waiting any winproc result
+    m_hEvtWndDisposed(CreateEventW(nullptr, MANUAL_RESET, INIT_NONSIGNALED, nullptr)),
     m_MtaOleReqWndClassAtom( 0 ),
     m_pfncClipViewerCallback( nullptr ),
     m_bRunClipboardNotifierThread( true ),
@@ -170,6 +233,7 @@ CMtaOleClipboard::CMtaOleClipboard( ) :
     m_hEvtThrdReady  = CreateEventW( nullptr, MANUAL_RESET, INIT_NONSIGNALED, nullptr );
 
     OSL_ASSERT( nullptr != m_hEvtThrdReady );
+    SAL_WARN_IF(!m_hEvtWndDisposed, "dtrans", "CreateEventW failed: m_hEvtWndDisposed is nullptr");
 
     s_theMtaOleClipboardInst = this;
 
@@ -253,11 +317,10 @@ HRESULT CMtaOleClipboard::flushClipboard( )
 
     MsgCtx  aMsgCtx;
 
-    sendMessage( MSG_FLUSHCLIPBOARD,
-                 static_cast< WPARAM >( 0 ),
-                 reinterpret_cast< LPARAM >( &aMsgCtx ) );
+    const bool bWaitSuccess = postMessage(MSG_FLUSHCLIPBOARD, 0, reinterpret_cast<LPARAM>(&aMsgCtx))
+                              && aMsgCtx.aCondition.wait(m_hEvtWndDisposed);
 
-    return aMsgCtx.hr;
+    return bWaitSuccess ? aMsgCtx.hr : E_ABORT;
 }
 
 HRESULT CMtaOleClipboard::getClipboard( IDataObject** ppIDataObject )
@@ -279,11 +342,11 @@ HRESULT CMtaOleClipboard::getClipboard( IDataObject** ppIDataObject )
 
     MsgCtx    aMsgCtx;
 
-    sendMessage( MSG_GETCLIPBOARD,
-                 reinterpret_cast< WPARAM >( &lpStream ),
-                 reinterpret_cast< LPARAM >( &aMsgCtx ) );
+    const bool bWaitSuccess = postMessage(MSG_GETCLIPBOARD, reinterpret_cast<WPARAM>(&lpStream),
+                                          reinterpret_cast<LPARAM>(&aMsgCtx))
+                              && aMsgCtx.aCondition.wait(m_hEvtWndDisposed);
 
-    HRESULT hr = aMsgCtx.hr;
+    HRESULT hr = bWaitSuccess ? aMsgCtx.hr : E_ABORT;
 
     if ( SUCCEEDED( hr ) )
     {
@@ -342,7 +405,11 @@ bool CMtaOleClipboard::registerClipViewer( LPFNC_CLIPVIEWER_CALLBACK_t pfncClipV
 
     OSL_ENSURE( GetCurrentThreadId( ) != m_uOleThreadId, "registerClipViewer from within the OleThread called" );
 
-    sendMessage(MSG_REGCLIPVIEWER, reinterpret_cast<WPARAM>(pfncClipViewerCallback), 0);
+    MsgCtx aMsgCtx;
+
+    if (postMessage(MSG_REGCLIPVIEWER, reinterpret_cast<WPARAM>(pfncClipViewerCallback),
+                    reinterpret_cast<LPARAM>(&aMsgCtx)))
+        aMsgCtx.aCondition.wait(m_hEvtWndDisposed);
 
     return false;
 }
@@ -481,6 +548,7 @@ LRESULT CALLBACK CMtaOleClipboard::mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARA
             OSL_ASSERT( aMsgCtx );
 
             aMsgCtx->hr = CMtaOleClipboard::onGetClipboard( reinterpret_cast< LPSTREAM* >(wParam) );
+            aMsgCtx->aCondition.set( );
         }
         break;
 
@@ -490,12 +558,19 @@ LRESULT CALLBACK CMtaOleClipboard::mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARA
             OSL_ASSERT( aMsgCtx );
 
             aMsgCtx->hr = CMtaOleClipboard::onFlushClipboard( );
+            aMsgCtx->aCondition.set( );
         }
         break;
 
     case MSG_REGCLIPVIEWER:
-        pImpl->onRegisterClipViewer(
-            reinterpret_cast<CMtaOleClipboard::LPFNC_CLIPVIEWER_CALLBACK_t>(wParam));
+        {
+            MsgCtx* pMsgCtx = reinterpret_cast<MsgCtx*>(lParam);
+            SAL_WARN_IF(!pMsgCtx, "dtrans", "pMsgCtx is nullptr");
+
+            pImpl->onRegisterClipViewer(
+                reinterpret_cast<CMtaOleClipboard::LPFNC_CLIPVIEWER_CALLBACK_t>(wParam));
+            pMsgCtx->aCondition.set();
+        }
         break;
 
     case WM_CLIPBOARDUPDATE:
@@ -508,6 +583,7 @@ LRESULT CALLBACK CMtaOleClipboard::mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARA
 
     // force the sta thread to end
     case WM_DESTROY:
+        SetEvent(pImpl->m_hEvtWndDisposed); // stop waiting for conditions set by this wndproc
         PostQuitMessage( 0 );
         break;
 
diff --git a/dtrans/source/win32/clipb/MtaOleClipb.hxx b/dtrans/source/win32/clipb/MtaOleClipb.hxx
index fdd00088dbe8..f25019d0784c 100644
--- a/dtrans/source/win32/clipb/MtaOleClipb.hxx
+++ b/dtrans/source/win32/clipb/MtaOleClipb.hxx
@@ -87,6 +87,7 @@ private:
     unsigned                    m_uOleThreadId;
     HANDLE                      m_hEvtThrdReady;
     HWND                        m_hwndMtaOleReqWnd;
+    HANDLE                      m_hEvtWndDisposed;
     ATOM                        m_MtaOleReqWndClassAtom;
     LPFNC_CLIPVIEWER_CALLBACK_t m_pfncClipViewerCallback;
     bool                        m_bInRegisterClipViewer;


More information about the Libreoffice-commits mailing list