vcl/win/dtrans/WinClipboard.cxx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
New commits: commit b3922a8d0051a656228f80aeee5360692c9bba2e Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Mon Jul 15 18:55:50 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Jul 15 19:14:31 2024 +0200 Release the lock for getClipboard call to avoid deadlock The call stacks that deadlock in my testing: Thread A: CMtaOleClipboard::clipboardChangedNotifierThreadProc() win32u.dll!NtUserMsgWaitForMultipleObjectsEx() user32.dll!MsgWaitForMultipleObjects() vclplug_winlo.dll!`anonymous namespace'::Win32Condition::wait(void * hEvtAbort) Line 92 C++ vclplug_winlo.dll!CMtaOleClipboard::getClipboard(IDataObject * * ppIDataObject) Line 353 C++ vclplug_winlo.dll!CWinClipboard::getIDataObject() Line 158 C++ vclplug_winlo.dll!CDOTransferable::tryToGetIDataObjectIfAbsent() Line 413 C++ vclplug_winlo.dll!CDOTransferable::getClipboardData(CFormatEtc & aFormatEtc) Line 426 C++ vclplug_winlo.dll!CDOTransferable::getTransferData(const com::sun::star::datatransfer::DataFlavor & aFlavor) Line 252 C++ vcllo.dll!TransferableDataHelper::GetAny(const com::sun::star::datatransfer::DataFlavor & rFlavor, const rtl::OUString & rDestDoc) Line 1484 C++ vcllo.dll!TransferableDataHelper::GetSequence(const com::sun::star::datatransfer::DataFlavor & rFlavor, const rtl::OUString & rDestDoc) Line 2078 C++ vcllo.dll!TransferableDataHelper::InitFormats() Line 1344 C++ vcllo.dll!TransferableDataHelper::TransferableDataHelper(const com::sun::star::uno::Reference<com::sun::star::datatransfer::XTransferable> & rxTransferable) Line 1156 C++ svtlo.dll!TransferableClipboardListener::changedContents(const com::sun::star::datatransfer::clipboard::ClipboardEvent & rEventObject) Line 52 C++ vclplug_winlo.dll!comphelper::OInterfaceContainerHelper4<com::sun::star::datatransfer::clipboard::XClipboardListener>::NotifySingleListener<com::sun::star::datatransfer::clipboard::ClipboardEvent>::operator()(const com::sun::star::uno::Reference<com::sun::star::datatransfer::clipboard::XClipboardListener> & listener) Line 275 C++ vclplug_winlo.dll!comphelper::OInterfaceContainerHelper4<com::sun::star::datatransfer::clipboard::XClipboardListener>::forEach<comphelper::OInterfaceContainerHelper4<com::sun::star::datatransfer::clipboard::XClipboardListener>::NotifySingleListener<com::sun::star::datatransfer::clipboard::ClipboardEvent>>(std::unique_lock<std::mutex> & rGuard, const comphelper::OInterfaceContainerHelper4<com::sun::star::datatransfer::clipboard::XClipboardListener>::NotifySingleListener<com::sun::star::datatransfer::clipboard::ClipboardEvent> & func) Line 304 C++ vclplug_winlo.dll!comphelper::OInterfaceContainerHelper4<com::sun::star::datatransfer::clipboard::XClipboardListener>::notifyEach<com::sun::star::datatransfer::clipboard::ClipboardEvent>(std::unique_lock<std::mutex> & rGuard, void(com::sun::star::datatransfer::clipboard::XClipboardListener::*)(const com::sun::star::datatransfer::clipboard::ClipboardEvent &) NotificationMethod, const com::sun::star::datatransfer::clipboard::ClipboardEvent & Event) Line 327 C++ vclplug_winlo.dll!CWinClipboard::handleClipboardContentChanged() Line 302 C++ vclplug_winlo.dll!CWinClipboard::onClipboardContentChanged() Line 386 C++ vclplug_winlo.dll!CMtaOleClipboard::clipboardChangedNotifierThreadProc(void * pParam) Line 723 C++ ucrtbased.dll!thread_start<unsigned int (__cdecl*)(void *),1>(void * const parameter) Line 97 C++ kernel32.dll!BaseThreadInitThunk() ntdll.dll!RtlUserThreadStart() Thread B: CMtaOleClipboard::run() ntdll.dll!NtWaitForAlertByThreadId() ntdll.dll!RtlAcquireSRWLockExclusive() msvcp140d.dll!mtx_do_lock(_Mtx_internal_imp_t * mtx, const _timespec64 * target) Line 93 C++ msvcp140d.dll!_Mtx_lock(_Mtx_internal_imp_t * mtx) Line 165 C++ vclplug_winlo.dll!std::_Mutex_base::lock() Line 56 C++ vclplug_winlo.dll!std::unique_lock<std::mutex>::unique_lock<std::mutex>(std::mutex & _Mtx) Line 149 C++ vclplug_winlo.dll!CWinClipboard::onReleaseDataObject(CXNotifyingDataObject * theCaller) Line 363 C++ vclplug_winlo.dll!CXNotifyingDataObject::Release() Line 77 C++ combase.dll!CStdIdentity::ReleaseCtrlUnk::__l5::<lambda>() Line 1408 C++ combase.dll!ObjectMethodExceptionHandlingAction<void <lambda>(void)>(CStdIdentity::ReleaseCtrlUnk::__l5::void <lambda>(void) action, ObjectMethodExceptionHandlingInfo * pExceptionHandlingInfo, ExceptionHandlingResult * pExceptionHandlingResult, void * __formal) Line 135 C++ combase.dll!CStdIdentity::ReleaseCtrlUnk(unsigned long dwDisconnectType) Line 1411 C++ [Inline Frame] combase.dll!ObjectLibrary::ReferencedPtr<CObjectContext>::operator int ObjectLibrary::Details::BoolStruct::*() Line 1313 C++ combase.dll!CStdMarshal::DisconnectWorker_ReleasesLock(unsigned long dwType, bool logEventIsActive, CObjectContext * explicitServerContext, bool performCallback, CIDObject * pIDDelayRelease) Line 4783 C++ combase.dll!CStdMarshal::Disconnect(unsigned long dwType) Line 4452 C++ [Inline Frame] combase.dll!CStdMarshal::HandlePendingDisconnect(HRESULT) Line 4285 C++ combase.dll!CRemoteUnknown::RemReleaseWorker(unsigned short cInterfaceRefs, tagREMINTERFACEREF * InterfaceRefs, int fTopLevel) Line 1307 C++ rpcrt4.dll!Invoke() rpcrt4.dll!Ndr64StubWorker() rpcrt4.dll!NdrStubCall3() combase.dll!CStdStubBuffer_Invoke(IRpcStubBuffer * This, tagRPCOLEMESSAGE * prpcmsg, IRpcChannelBuffer * pRpcChannelBuffer) Line 1479 C++ [Inline Frame] combase.dll!InvokeStubWithExceptionPolicyAndTracing::__l6::<lambda_c9f3956a20c9da92a64affc24fdd69ec>::operator()() Line 1151 C++ combase.dll!ObjectMethodExceptionHandlingAction<<lambda_c9f3956a20c9da92a64affc24fdd69ec>>(InvokeStubWithExceptionPolicyAndTracing::__l6::<lambda_c9f3956a20c9da92a64affc24fdd69ec> action, ObjectMethodExceptionHandlingInfo * pExceptionHandlingInfo, ExceptionHandlingResult * pExceptionHandlingResult, void *) Line 94 C++ [Inline Frame] combase.dll!InvokeStubWithExceptionPolicyAndTracing(IRpcStubBuffer * pMsg, tagRPCOLEMESSAGE *) Line 1149 C++ combase.dll!DefaultStubInvoke(bool bIsAsyncBeginMethod, IServerCall * pServerCall, IRpcChannelBuffer * pChannel, IRpcStubBuffer * pStub, unsigned long * pdwFault) Line 1218 C++ combase.dll!SyncServerCall::StubInvoke(IRpcChannelBuffer * pChannel, IRpcStubBuffer * pStub, unsigned long * pdwFault) Line 791 C++ [Inline Frame] combase.dll!StubInvoke(tagRPCOLEMESSAGE * pMsg, const _GUID &) Line 1483 C++ combase.dll!ServerCall::ContextInvoke(tagIPIDEntry * ipidEntry) Line 1421 C++ [Inline Frame] combase.dll!DefaultInvokeInApartment(ServerCall *) Line 3257 C++ combase.dll!ReentrantSTAInvokeInApartment(ServerCall * serverCall, tagIPIDEntry * ipidEntry) Line 110 C++ combase.dll!ComInvokeWithLockAndIPID(ServerCall * pServerCall, tagIPIDEntry * pIPIDEntry) Line 2152 C++ combase.dll!ThreadDispatch(ServerCall * pServerCall) Line 1637 C++ combase.dll!ThreadWndProc(HWND__ * window, unsigned int message, unsigned __int64 wparam, __int64 params) Line 720 C++ user32.dll!UserCallWinProcCheckWow() user32.dll!DispatchMessageWorker() [Inline Frame] combase.dll!CCliModalLoop::MyDispatchMessage(tagMSG *) Line 2959 C++ combase.dll!CCliModalLoop::PeekRPCAndDDEMessage() Line 2563 C++ combase.dll!CCliModalLoop::BlockFn(void * * ahEvent, unsigned long cEvents, unsigned long * lpdwSignaled) Line 2055 C++ combase.dll!ModalLoop(CSyncClientCall * pClientCall) Line 169 C++ [Inline Frame] combase.dll!ThreadSendReceive(tagRPCOLEMESSAGE *) Line 7259 C++ [Inline Frame] combase.dll!CSyncClientCall::SwitchAptAndDispatchCall(tagRPCOLEMESSAGE * pMessage) Line 5735 C++ combase.dll!CSyncClientCall::SendReceive2(tagRPCOLEMESSAGE * pMessage, unsigned long * pstatus) Line 5297 C++ combase.dll!SyncClientCallRetryContext::SendReceiveWithRetry(tagRPCOLEMESSAGE * pMsg, unsigned long * pulStatus, ClientCall * pClientCall, bool * pbIsAutoRetry) Line 1502 C++ combase.dll!CSyncClientCall::SendReceiveInRetryContext(SyncClientCallRetryContext * pRetryContext, tagRPCOLEMESSAGE * pMsg, unsigned long * pulStatus) Line 582 C++ combase.dll!ClassicSTAThreadSendReceive(CSyncClientCall * pClientCall, tagRPCOLEMESSAGE * pMsg, unsigned long * pulStatus) Line 564 C++ combase.dll!CSyncClientCall::SendReceive(tagRPCOLEMESSAGE * pMessage, unsigned long * pulStatus) Line 787 C++ combase.dll!CClientChannel::SendReceive(tagRPCOLEMESSAGE * pMessage, unsigned long * pulStatus) Line 659 C++ combase.dll!NdrExtpProxySendReceive(void * pThis, _MIDL_STUB_MESSAGE * pStubMsg) Line 1989 C++ rpcrt4.dll!NdrpClientCall3() combase.dll!ObjectStublessClient(void * ParamAddress, __int64 * FloatRegisters, long Method) Line 366 C++ combase.dll!ObjectStubless() Line 176 combase.dll!CStdMarshal::RemoteAddRef(tagIPIDEntry * pIPIDEntry, OXIDEntry * pOXIDEntry, unsigned long cStrongNeed, unsigned long cSecureNeed, int fGiveToCaller) Line 8489 C++ [Inline Frame] combase.dll!CStdMarshal::GetNeededRefs(tagSTDOBJREF *) Line 3654 C++ combase.dll!CStdMarshal::ConnectCliIPIDEntry(tagSTDOBJREF * pStd, OXIDEntry * pOXIDEntry, tagIPIDEntry * pEntry) Line 3338 C++ combase.dll!CStdMarshal::MakeCliIPIDEntry(const _GUID & riid, tagSTDOBJREF * pStd, OXIDEntry * pOXIDEntry, tagIPIDEntry * * ppEntry) Line 3108 C++ combase.dll!CStdMarshal::UnmarshalIPID(const _GUID & riid, tagSTDOBJREF * pStd, OXIDEntry * pOXIDEntry, void * * ppv) Line 2621 C++ combase.dll!CStdMarshal::UnmarshalObjRef(tagOBJREF & objref, void * * ppv) Line 2479 C++ combase.dll!UnmarshalSwitch(void * pv) Line 2112 C++ combase.dll!UnmarshalObjRef(tagOBJREF & objref, EffectiveUnmarshalingPolicy policy, void * * ppv, int fBypassActLock, CBaseCall * callMarshalingContext, CStdMarshal * * ppStdMarshal) Line 2261 C++ combase.dll!InternalGetWindowPropInterface2(HWND__ * hWnd, unsigned __int64 dwCookie, int fCallStrongNamedProcesses, const _GUID & iid, void * * ppv, int * pfLocal) Line 285 C++ ole32.dll!UnmarshalFromEndpointProperty(HWND__ * hWnd, int fDragDrop, int fCallStrongNamedProcesses, IUnknown * * ppUnk, int * pfLocal) Line 407 C++ ole32.dll!GetInterfaceFromWindowProp(HWND__ * hWnd, const _GUID & fCallStrongNamedProcesses, int ppunk, IUnknown * *) Line 440 C++ ole32.dll!CClipDataObject::CacheDataPointer() Line 223 C++ ole32.dll!CClipDataObject::QueryInterface(const _GUID & riid, void * * ppvObj) Line 886 C++ [Inline Frame] combase.dll!IUnknown::QueryInterface(INoMarshal * *) Line 138 C++ combase.dll!CoMarshalInterface(IStream * pStm, const _GUID & riid, IUnknown * pUnk, unsigned long dwDestCtx, void * pvDestCtx, unsigned long mshlflags) Line 1133 C++ combase.dll!wCoMarshalInterThreadInterfaceInStream(const _GUID & riid, IUnknown * pUnk, IStream * * ppStm) Line 1046 C++ combase.dll!CoMarshalInterThreadInterfaceInStream(const _GUID & riid, IUnknown * pUnk, IStream * * ppStm) Line 709 C++ vclplug_winlo.dll!MarshalIDataObjectInStream(IDataObject * pIDataObject, IStream * * ppStream) Line 158 C++ vclplug_winlo.dll!CMtaOleClipboard::onGetClipboard(IStream * * ppStream) Line 465 C++ vclplug_winlo.dll!CMtaOleClipboard::mtaOleReqWndProc(HWND__ * hWnd, unsigned int uMsg, unsigned __int64 wParam, __int64 lParam) Line 547 C++ user32.dll!UserCallWinProcCheckWow() user32.dll!DispatchMessageWorker() vclplug_winlo.dll!CMtaOleClipboard::run() Line 656 C++ vclplug_winlo.dll!CMtaOleClipboard::oleThreadProc(void * pParam) Line 673 C++ ucrtbased.dll!thread_start<unsigned int (__cdecl*)(void *),1>(void * const parameter) Line 97 C++ kernel32.dll!BaseThreadInitThunk() ntdll.dll!RtlUserThreadStart() Thread A locks the mutex, and calls CMtaOleClipboard::getClipboard, which is synchronous; the call is marshaled to Thread B, which eventually tries to release a data object, which requires the mutex. Change-Id: I5ad8847b98ca23ad84c0595a2baad2c13f1e809e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170504 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Jenkins diff --git a/vcl/win/dtrans/WinClipboard.cxx b/vcl/win/dtrans/WinClipboard.cxx index 3c9f57a1e250..be0266addd18 100644 --- a/vcl/win/dtrans/WinClipboard.cxx +++ b/vcl/win/dtrans/WinClipboard.cxx @@ -147,12 +147,13 @@ css::uno::Reference<css::datatransfer::XTransferable> CWinClipboard::getContents IDataObjectPtr CWinClipboard::getIDataObject() { - std::unique_lock aGuard(m_aMutex); - - if (m_bDisposed) - throw lang::DisposedException("object is already disposed", - static_cast<XClipboardEx*>(this)); + { + std::unique_lock aGuard(m_aMutex); + if (m_bDisposed) + throw lang::DisposedException("object is already disposed", + static_cast<XClipboardEx*>(this)); + } // get the current dataobject from clipboard IDataObjectPtr pIDataObject; HRESULT hr = m_MtaOleClipboard.getClipboard(&pIDataObject);