diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2019-02-04 23:12:42 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2019-02-05 10:09:16 +0100 |
commit | 11a2809e369b2a6fcbb2d7f0db131a945557c6e2 (patch) | |
tree | a98f11ef8986e2ddb37e790f5e72df4615e37d49 /dtrans | |
parent | e436a61a89efb28d5a087b695bb51c71bdd9f62c (diff) |
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@collabora.com>
Diffstat (limited to 'dtrans')
-rw-r--r-- | dtrans/source/win32/clipb/MtaOleClipb.cxx | 102 | ||||
-rw-r--r-- | dtrans/source/win32/clipb/MtaOleClipb.hxx | 1 |
2 files changed, 90 insertions, 13 deletions
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; |