vcl/win/dtrans/WinClipboard.cxx | 52 ++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 23 deletions(-)
New commits: commit 1b79853658327dea6a151e19be9f3b149d9139ad Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Nov 3 00:10:17 2024 +0500 Commit: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> CommitDate: Fri Nov 8 11:50:30 2024 +0100 Related: tdf#163730 Avoid deadlock Seen locally, with main thread querying clipboard state: vclplug_winlo.dll!std::unique_lock<std::mutex>::unique_lock<std::mutex>(std::mutex & _Mtx) Line 145 vclplug_winlo.dll!CWinClipboard::getContents() Line 109 vcllo.dll!TransferableDataHelper::CreateFromClipboard(const com::sun::star::uno::Reference<com::sun::star::datatransfer::clipboard::XClipboard> & rClipboard) Line 2162 vcllo.dll!TransferableDataHelper::CreateFromSystemClipboard(vcl::Window * pWindow) Line 2188 swlo.dll!SwBaseShell::StateClpbrd(SfxItemSet & rSet) Line 602 swlo.dll!SfxStubSwBaseShellStateClpbrd(SfxShell * pShell, SfxItemSet & rSet) Line 2220 sfxlo.dll!SfxDispatcher::FillState_(const SfxSlotServer & rSvr, SfxItemSet & rState, const SfxSlot * pRealSlot) Line 1726 sfxlo.dll!SfxBindings::Update_Impl(SfxStateCache & rCache) Line 267 sfxlo.dll!SfxBindings::NextJob_Impl(const Timer * pTimer) Line 1280 sfxlo.dll!SfxBindings::NextJob(Timer * pTimer) Line 1225 sfxlo.dll!SfxBindings::LinkStubNextJob(void * instance, Timer * data) Line 1220 vcllo.dll!Link<Timer *,void>::Call(Timer * data) Line 111 vcllo.dll!Timer::Invoke() Line 75 vcllo.dll!Scheduler::CallbackTaskScheduling() Line 509 vcllo.dll!SalTimer::CallCallback() Line 53 vclplug_winlo.dll!WinSalTimer::ImplHandleElapsedTimer() Line 169 vclplug_winlo.dll!ImplSalYield(bool bWait, bool bHandleAllCurrentEvents) Line 525 vclplug_winlo.dll!WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents) Line 581 vcllo.dll!ImplYield(bool i_bWait, bool i_bAllEvents) Line 385 vcllo.dll!Application::Yield() Line 473 vcCMtaOleClipboard::runllo.dll!Application::Execute() Line 361 sofficeapp.dll!desktop::Desktop::Main() Line 1679 CMtaOleClipboard::clipboardChangeNotifier thread holding CWinClipboard's mutex in handleClipboardContentChanged, and waiting for the destruction of IDataObject released from m_foreignContent (which was redirected to CMtaOleClipboard::run thread): vclplug_winlo.dll!sal::systools::COMReference<IDataObject>::release(IDataObject * ptr) Line 235 vclplug_winlo.dll!sal::systools::COMReference<IDataObject>::~COMReference<IDataObject>() Line 163 vclplug_winlo.dll!CAPNDataObject::~CAPNDataObject() Line 97 vclplug_winlo.dll!CAPNDataObject::`scalar deleting destructor'(unsigned int) vclplug_winlo.dll!CAPNDataObject::Release() Line 137 vclplug_winlo.dll!sal::systools::COMReference<IDataObject>::release(IDataObject * ptr) Line 235 vclplug_winlo.dll!sal::systools::COMReference<IDataObject>::~COMReference<IDataObject>() Line 163 vclplug_winlo.dll!CDOTransferable::~CDOTransferable() vclplug_winlo.dll!CDOTransferable::`scalar deleting destructor'(unsigned int) cppuhelper3MSC.dll!cppu::OWeakObject::release() Line 230 vclplug_winlo.dll!cppu::WeakImplHelper<com::sun::star::datatransfer::XTransferable>::release() Line 115 vclplug_winlo.dll!com::sun::star::uno::Reference<com::sun::star::datatransfer::XTransferable>::clear() Line 234 vclplug_winlo.dll!CWinClipboard::handleClipboardContentChanged() Line 291 vclplug_winlo.dll!CWinClipboard::onClipboardContentChanged() Line 385 vclplug_winlo.dll!CMtaOleClipboard::clipboardChangedNotifierThreadProc(void * pParam) Line 721 and CMtaOleClipboard::run thread waiting for CWinClipboard's mutex in CWinClipboard::onReleaseDataObject: vclplug_winlo.dll!std::_Mutex_base::lock() Line 52 vclplug_winlo.dll!std::unique_lock<std::mutex>::unique_lock<std::mutex>(std::mutex & _Mtx) Line 145 vclplug_winlo.dll!CWinClipboard::onReleaseDataObject(CXNotifyingDataObject & theCaller) Line 362 vclplug_winlo.dll!CXNotifyingDataObject::Release() Line 75 ole32.dll!CClipDataObject::Release() Line 960 combase.dll!... rpcrt4.dll!Invoke() rpcrt4.dll!Ndr64StubWorker(void *,void *,struct _RPC_MESSAGE *,struct _MIDL_SERVER_INFO_ *,long (*const *)(void),struct _MIDL_SYNTAX_INFO *,unsigned long *) rpcrt4.dll!NdrStubCall3() combase.dll!... user32.dll!UserCallWinProcCheckWow(struct _ACTIVATION_CONTEXT *,__int64 (*)(struct tagWND *,unsigned int,unsigned __int64,__int64),struct HWND__ *,enum _WM_VALUE,unsigned __int64,__int64,void *,int) user32.dll!DispatchMessageWorker() vclplug_winlo.dll!CMtaOleClipboard::run() Line 655 vclplug_winlo.dll!CMtaOleClipboard::oleThreadProc(void * pParam) Line 673 Caused by changes in commit 2e0664015255ffc0f76a11a9cb254564b34de496 (tdf#148647: make sure to update own content on Win clipboard change, 2024-07-14). Change-Id: I26d35726f3d3f650a2db2ac63709ed820a60fc4e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175956 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Jenkins (cherry picked from commit 9f53d40fd19b22fe1bdbf64e8ce751cf53f4f517) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175919 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176161 Tested-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> Reviewed-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> diff --git a/vcl/win/dtrans/WinClipboard.cxx b/vcl/win/dtrans/WinClipboard.cxx index be0266addd18..5760155beaa1 100644 --- a/vcl/win/dtrans/WinClipboard.cxx +++ b/vcl/win/dtrans/WinClipboard.cxx @@ -283,33 +283,39 @@ void SAL_CALL CWinClipboard::removeClipboardListener( void CWinClipboard::handleClipboardContentChanged() { - std::unique_lock aGuard(m_aMutex); - if (m_bDisposed) - return; + // The object must be destroyed only outside of the mutex lock, because it may call + // CWinClipboard::onReleaseDataObject in another thread of this process + css::uno::Reference<css::datatransfer::XTransferable> old_foreignContent; + { + std::unique_lock aGuard(m_aMutex); + if (m_bDisposed) + return; - m_foreignContent.clear(); - // If new own content assignment is pending, do it; otherwise, clear it. - // This makes sure that there will be no stuck clipboard content. - m_pCurrentOwnClipContent = std::exchange(m_pNewOwnClipContent, nullptr); + old_foreignContent = std::move(m_foreignContent); // clear m_foreignContent + assert(!m_foreignContent.is()); + // If new own content assignment is pending, do it; otherwise, clear it. + // This makes sure that there will be no stuck clipboard content. + m_pCurrentOwnClipContent = std::exchange(m_pNewOwnClipContent, nullptr); - if (!maClipboardListeners.getLength(aGuard)) - return; + if (!maClipboardListeners.getLength(aGuard)) + return; - try - { - uno::Reference<datatransfer::XTransferable> rXTransf(getContents_noLock()); - datatransfer::clipboard::ClipboardEvent aClipbEvent(static_cast<XClipboard*>(this), - rXTransf); - maClipboardListeners.notifyEach( - aGuard, &datatransfer::clipboard::XClipboardListener::changedContents, aClipbEvent); - } - catch (const lang::DisposedException&) - { - OSL_FAIL("Service Manager disposed"); + try + { + uno::Reference<datatransfer::XTransferable> rXTransf(getContents_noLock()); + datatransfer::clipboard::ClipboardEvent aClipbEvent(static_cast<XClipboard*>(this), + rXTransf); + maClipboardListeners.notifyEach( + aGuard, &datatransfer::clipboard::XClipboardListener::changedContents, aClipbEvent); + } + catch (const lang::DisposedException&) + { + OSL_FAIL("Service Manager disposed"); - aGuard.unlock(); - // no further clipboard changed notifications - unregisterClipboardViewer(); + aGuard.unlock(); + // no further clipboard changed notifications + unregisterClipboardViewer(); + } } }