summaryrefslogtreecommitdiff
path: root/dtrans
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2019-02-04 23:12:42 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2019-02-05 10:09:16 +0100
commit11a2809e369b2a6fcbb2d7f0db131a945557c6e2 (patch)
treea98f11ef8986e2ddb37e790f5e72df4615e37d49 /dtrans
parente436a61a89efb28d5a087b695bb51c71bdd9f62c (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.cxx102
-rw-r--r--dtrans/source/win32/clipb/MtaOleClipb.hxx1
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;