vcl/win/dtrans/WinClipboard.cxx |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

New commits:
commit 171acae53f7b5f4f78dd395a10c89f779cb57494
Author:     Mike Kaganski <[email protected]>
AuthorDate: Thu Jan 9 10:49:48 2025 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Thu Jan 9 08:47:54 2025 +0100

    tdf#163083: try to release lock to avoid deadlock
    
    The minidump in the bug 
(https://bugs.documentfoundation.org/attachment.cgi?id=198431)
    shows these three stacks:
    
    1. VCL main thread:
    
      ntdll.dll!NtWaitForAlertByThreadId()
      ntdll.dll!RtlpAcquireSRWLockExclusiveContended()
      ntdll.dll!RtlAcquireSRWLockExclusive()
      msvcp140.dll!mtx_do_lock(_Mtx_internal_imp_t * mtx, const xtime * target) 
Line 103
      [Inline Frame] vclplug_winlo.dll!std::_Mutex_base::lock() Line 50
      [Inline Frame] 
vclplug_winlo.dll!std::unique_lock<std::mutex>::{ctor}(std::mutex &) Line 133
      vclplug_winlo.dll!CWinClipboard::getContents() Line 125
      sclo.dll!ScTabViewShell::GetClipData(vcl::Window * pWin) Line 542
      [Inline Frame] vbaobjlo.dll!ooo::vba::excel::implnPasteSpecial(const 
com::sun::star::uno::Reference<com::sun::star::frame::XModel> &) Line 235
      vbaobjlo.dll!ScVbaRange::PasteSpecial(const com::sun::star::uno::Any & 
Paste, const com::sun::star::uno::Any & Operation, const 
com::sun::star::uno::Any & SkipBlanks, const com::sun::star::uno::Any & 
Transpose) Line 2942
      mscx_uno.dll!`anonymous 
namespace'::cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, 
bridges::cpp_uno::shared::VtableSlot aVtableSlot, 
_typelib_TypeDescriptionReference * pReturnTypeRef, long nParams, 
_typelib_MethodParameter * pParams, void * pUnoReturn, void * * pUnoArgs, 
_uno_Any * * ppUnoExc) Line 214
      mscx_uno.dll!unoInterfaceProxyDispatch(_uno_Interface * pUnoI, const 
_typelib_TypeDescription * pMemberTD, void * pReturn, void * * pArgs, _uno_Any 
* * ppException) Line 430
      reflectionlo.dll!stoc_corefl::`anonymous 
namespace'::IdlInterfaceMethodImpl::invoke(const com::sun::star::uno::Any & 
rObj, com::sun::star::uno::Sequence<com::sun::star::uno::Any> & rArgs) Line 593
      mergedlo.dll!SbUnoObject::Notify(SfxBroadcaster & rBC, const SfxHint & 
rHint) Line 2246
      mergedlo.dll!SfxBroadcaster::Broadcast(const SfxHint & rHint) Line 36
      mergedlo.dll!SbxVariable::Broadcast(SfxHintId nHintId) Line 155
      mergedlo.dll!SbxValue::SbxValue(const SbxValue & r) Line 68
      mergedlo.dll!SbxVariable::SbxVariable(const SbxVariable & r) Line 49
      mergedlo.dll!SbxMethod::SbxMethod(const SbxMethod & r) Line 847
      mergedlo.dll!SbiRuntime::FindElement(SbxObject * pObj, unsigned long 
nOp1, unsigned long nOp2, ErrCode nNotFound, bool bLocal, bool bStatic) Line 
3703
      mergedlo.dll!SbiRuntime::StepELEM(unsigned long nOp1, unsigned long nOp2) 
Line 4189
      mergedlo.dll!SbiRuntime::Step() Line 811
      [Inline Frame] mergedlo.dll!`anonymous-namespace'::RunInitGuard::run() 
Line 1017
      mergedlo.dll!SbModule::Run(SbMethod * pMeth) Line 1177
      mergedlo.dll!SbModule::Notify(SfxBroadcaster & rBC, const SfxHint & 
rHint) Line 776
      mergedlo.dll!SfxBroadcaster::Broadcast(const SfxHint & rHint) Line 36
      mergedlo.dll!SbMethod::Broadcast(SfxHintId nHintId) Line 2121
      mergedlo.dll!SbxValue::Get(SbxValues & rRes) Line 290
      mergedlo.dll!SbMethod::Call(SbxValue * pRet, SbxVariable * pCaller) Line 
2078
      mergedlo.dll!basprov::BasicScriptImpl::invoke(const 
com::sun::star::uno::Sequence<com::sun::star::uno::Any> & aParams, 
com::sun::star::uno::Sequence<short> & aOutParamIndex, 
com::sun::star::uno::Sequence<com::sun::star::uno::Any> & aOutParam) Line 264
      mergedlo.dll!SfxObjectShell::CallXScript(const 
com::sun::star::uno::Reference<com::sun::star::uno::XInterface> & 
_rxScriptContext, const rtl::OUString & _rScriptURL, const 
com::sun::star::uno::Sequence<com::sun::star::uno::Any> & aParams, 
com::sun::star::uno::Any & aRet, com::sun::star::uno::Sequence<short> & 
aOutParamIndex, com::sun::star::uno::Sequence<com::sun::star::uno::Any> & 
aOutParam, bool bRaiseError, const com::sun::star::uno::Any * pCaller) Line 1545
      
mergedlo.dll!SfxApplication::OfaExec_Impl::__l120::<lambda_2>::operator()(long 
nDialogResult) Line 1768
      [Inline Frame] mergedlo.dll!std::_Func_class<void,long>::operator()(long 
<_Args_0>) Line 869
      mergedlo.dll!Dialog::EndDialog(__int64 nResult) Line 1212
      [Inline Frame] mergedlo.dll!Link<weld::Button &,void>::Call(weld::Button 
&) Line 111
      [Inline Frame] mergedlo.dll!weld::Button::signal_clicked() Line 1508
      [Inline Frame] mergedlo.dll!SalInstanceButton::ClickHdl(Button *) Line 
2941
      mergedlo.dll!SalInstanceButton::LinkStubClickHdl(void * instance, Button 
* data) Line 2929
      [Inline Frame] mergedlo.dll!std::_Func_class<void>::operator()() Line 869
      [Inline Frame] 
mergedlo.dll!Control::ImplCallEventListenersAndHandler(VclEventId) Line 311
      mergedlo.dll!Button::Click() Line 130
      mergedlo.dll!PushButton::Tracking(const TrackingEvent & rTEvt) Line 1324
      mergedlo.dll!vcl::Window::EndTracking(TrackingEventFlags nFlags) Line 341
      mergedlo.dll!ImplHandleMouseEvent(const VclPtr<vcl::Window> & xWindow, 
NotifyEventType nSVEvent, bool bMouseLeave, __int64 nX, __int64 nY, unsigned 
__int64 nMsgTime, unsigned short nCode, MouseEventModifiers nMode) Line 715
      mergedlo.dll!ImplHandleSalMouseButtonUp(vcl::Window * pWindow, const 
SalMouseEvent * pEvent) Line 2353
      mergedlo.dll!ImplWindowFrameProc(vcl::Window * _pWindow, SalEvent nEvent, 
const void * pEvent) Line 2702
      mergedlo.dll!SalFrame::CallCallback(SalEvent nEvent, const void * pEvent) 
Line 312
      vclplug_winlo.dll!ImplHandleMouseMsg(HWND__ * hWnd, unsigned int nMsg, 
unsigned __int64 wParam, __int64 lParam) Line 3318
      vclplug_winlo.dll!SalFrameWndProc(HWND__ * hWnd, unsigned int nMsg, 
unsigned __int64 wParam, __int64 lParam, bool & rDef) Line 5876
      vclplug_winlo.dll!SalFrameWndProcW(HWND__ * hWnd, unsigned int nMsg, 
unsigned __int64 wParam, __int64 lParam) Line 6231
      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!ImplSalDispatchMessage(const tagMSG * pMsg) Line 476
      vclplug_winlo.dll!ImplSalYield(bool bWait, bool bHandleAllCurrentEvents) 
Line 552
      vclplug_winlo.dll!WinSalInstance::DoYield(bool bWait, bool 
bHandleAllCurrentEvents) Line 581
      mergedlo.dll!ImplYield(bool i_bWait, bool i_bAllEvents) Line 387
      mergedlo.dll!Application::Execute() Line 360
      mergedlo.dll!desktop::Desktop::Main() Line 1652
      mergedlo.dll!ImplSVMain() Line 229
      [Inline Frame] mergedlo.dll!SVMain() Line 247
      mergedlo.dll!soffice_main() Line 99
      [Inline Frame] soffice.bin!sal_main() Line 51
      soffice.bin!main(int argc, char * * argv) Line 49
      [Inline Frame] soffice.bin!invoke_main() Line 78
      soffice.bin!__scrt_common_main_seh() Line 288
      kernel32.dll!BaseThreadInitThunk()
      ntdll.dll!RtlUserThreadStart()
    
    2. Clipboard thread:
    
      ntdll.dll!NtWaitForAlertByThreadId()
      ntdll.dll!RtlpWaitOnCriticalSection()
      ntdll.dll!RtlpEnterCriticalSectionContended()
      ntdll.dll!RtlEnterCriticalSection()
      sal3.dll!osl_acquireMutex(_oslMutexImpl * Mutex) Line 65
      [Inline Frame] vclplug_winlo.dll!osl::Mutex::acquire() Line 63
      vclplug_winlo.dll!SalYieldMutex::doAcquire(unsigned long nLockCount) Line 
148
      [Inline Frame] mergedlo.dll!comphelper::SolarMutex::acquire(unsigned 
long) Line 86
      [Inline Frame] 
mergedlo.dll!osl::Guard<comphelper::SolarMutex>::{ctor}(comphelper::SolarMutex 
& t) Line 144
      [Inline Frame] mergedlo.dll!SolarMutexGuard::{ctor}() Line 1340
      mergedlo.dll!TransferableHelper::getTransferDataFlavors() Line 477
      vclplug_winlo.dll!CFormatRegistrar::RegisterFormats(const 
com::sun::star::uno::Reference<com::sun::star::datatransfer::XTransferable> & 
aXTransferable, CFormatEtcContainer & aFormatEtcContainer) Line 145
      [Inline Frame] 
vclplug_winlo.dll!CXTDataObject::InitializeFormatEtcContainer() Line 648
      vclplug_winlo.dll!CXTDataObject::EnumFormatEtc(unsigned long dwDirection, 
IEnumFORMATETC * * ppenumFormatetc) Line 549
      ole32.dll!SetClipboardFormats(HWND__ * hClipWnd, IDataObject * pDataObj) 
Line 4482
      ole32.dll!OleSetClipboardInternal(IDataObject * pDataObject, IDataObject 
* pSourceDataObject, void * * ppDataObjectMTAAddress, const wchar_t * 
pszCallerPackageFullName, unsigned long pid) Line 3750
      ole32.dll!OleSetClipboard(IDataObject * pDataObject) Line 3602
      [Inline Frame] 
vclplug_winlo.dll!CMtaOleClipboard::onSetClipboard::__l2::<lambda_1>::operator()()
 Line 464
      [Inline Frame] vclplug_winlo.dll!sal::systools::RetryIfFailed(unsigned 
int) Line 31
      [Inline Frame] 
vclplug_winlo.dll!CMtaOleClipboard::onSetClipboard(IDataObject *) Line 463
      vclplug_winlo.dll!CMtaOleClipboard::mtaOleReqWndProc(HWND__ * hWnd, 
unsigned int uMsg, unsigned __int64 wParam, __int64 lParam) Line 541
      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()
      [Inline Frame] vclplug_winlo.dll!CMtaOleClipboard::run() Line 668
      vclplug_winlo.dll!CMtaOleClipboard::oleThreadProc(void * pParam) Line 685
      ucrtbase.dll!thread_start<unsigned int (__cdecl*)(void *),1>()
      kernel32.dll!BaseThreadInitThunk()
      ntdll.dll!RtlUserThreadStart()
    
    3. Clipboard content changed notification thread:
    
      win32u.dll!NtUserMsgWaitForMultipleObjectsEx()
      combase.dll!CCliModalLoop::BlockFn(void * * ahEvent, unsigned long 
cEvents, unsigned long * lpdwSignaled) Line 2105
      combase.dll!ModalLoop(CSyncClientCall * pClientCall) Line 171
      combase.dll!ClassicSTAThreadDispatchCrossApartmentCall(tagRPCOLEMESSAGE * 
pMessage, OXIDEntry * pOXIDEntry, CSyncClientCall * pClientCall) Line 324
      [Inline Frame] 
combase.dll!CSyncClientCall::SwitchAptAndDispatchCall(tagRPCOLEMESSAGE * 
pMessage) Line 5704
      combase.dll!CSyncClientCall::SendReceive2(tagRPCOLEMESSAGE * pMessage, 
unsigned long * pstatus) Line 5310
      [Inline Frame] 
combase.dll!SyncClientCallRetryContext::SendReceiveWithRetry(tagRPCOLEMESSAGE 
*) Line 1493
      [Inline Frame] 
combase.dll!CSyncClientCall::SendReceiveInRetryContext(SyncClientCallRetryContext
 *) Line 581
      combase.dll!ClassicSTAThreadSendReceive(CSyncClientCall * pClientCall, 
tagRPCOLEMESSAGE * pMsg, unsigned long * pulStatus) Line 563
      combase.dll!CSyncClientCall::SendReceive(tagRPCOLEMESSAGE * pMessage, 
unsigned long * pulStatus) Line 797
      [Inline Frame] combase.dll!CClientChannel::SendReceive(tagRPCOLEMESSAGE 
*) Line 674
      combase.dll!NdrExtpProxySendReceive(void * pThis, _MIDL_STUB_MESSAGE * 
pStubMsg) Line 1899
      rpcrt4.dll!NdrpClientCall3()
      combase.dll!ObjectStublessClient(void * ParamAddress, __int64 * 
FloatRegisters, long Method) Line 366
      combase.dll!ObjectStubless() Line 176
      [Inline Frame] combase.dll!RemoteReleaseRifRefHelper(IRemUnknown *) Line 
8720
      combase.dll!RemoteReleaseRifRef(CStdMarshal * pMarshal, OXIDEntry * 
pOXIDEntry, unsigned short cRifRef, tagREMINTERFACEREF * pRifRef) Line 8627
      combase.dll!CStdMarshal::DisconnectCliIPIDs(unsigned long) Line 5357
      combase.dll!CStdMarshal::DisconnectWorker_ReleasesLock(unsigned long 
dwType, bool logEventIsActive, CObjectContext * explicitServerContext, bool 
performCallback, CIDObject * pIDDelayRelease, const void *) Line 4676
      combase.dll!CStdMarshal::Disconnect(unsigned long dwType, const void * 
callerAddressForDiagnostics) Line 4441
      combase.dll!CStdIdentity::~CStdIdentity() Line 388
      combase.dll!CStdIdentity::`scalar deleting destructor'(unsigned int)
      [Inline Frame] 
combase.dll!CStdIdentity::CInternalUnk::ReleaseWithCallerAddress(const void *) 
Line 945
      combase.dll!CStdIdentity::CInternalUnk::Release() Line 851
      [Inline Frame] 
vclplug_winlo.dll!sal::systools::COMReference<IDataObject>::release(IDataObject 
* ptr) Line 229
      [Inline Frame] 
vclplug_winlo.dll!sal::systools::COMReference<IDataObject>::{dtor}() Line 158
      [Inline Frame] vclplug_winlo.dll!CAPNDataObject::{dtor}() Line 97
      vclplug_winlo.dll!CAPNDataObject::`scalar deleting destructor'(unsigned 
int)
      vclplug_winlo.dll!CAPNDataObject::Release() Line 140
      [Inline Frame] 
vclplug_winlo.dll!sal::systools::COMReference<IDataObject>::release(IDataObject 
* ptr) Line 229
      [Inline Frame] 
vclplug_winlo.dll!sal::systools::COMReference<IDataObject>::{dtor}() Line 158
      vclplug_winlo.dll!CDOTransferable::`scalar deleting destructor'(unsigned 
int)
      [Inline Frame] 
vclplug_winlo.dll!com::sun::star::uno::Reference<com::sun::star::datatransfer::XTransferable>::{dtor}()
 Line 114
      vclplug_winlo.dll!CWinClipboard::handleClipboardContentChanged() Line 330
      vclplug_winlo.dll!CWinClipboard::onClipboardContentChanged() Line 412
      
vclplug_winlo.dll!CMtaOleClipboard::clipboardChangedNotifierThreadProc(void * 
pParam) Line 699
      ucrtbase.dll!thread_start<unsigned int (__cdecl*)(void *),1>()
      kernel32.dll!BaseThreadInitThunk()
      ntdll.dll!RtlUserThreadStart()
    
    Thread #3 has locked m_aMutex in 
CWinClipboard::handleClipboardContentChanged, and
    tries to destroy CDOTransferable in the reference dtor. That delegates to 
another
    thread (not entirely clear which, but could be either thread #1 or #2); at 
this
    point, thread #1 is in CWinClipboard::getContents waiting for the same 
m_aMutex,
    and thread #2 is in TransferableHelper::getTransferDataFlavors, waiting for 
the
    solar mutex (locked by VCL main thread in basprov::BasicScriptImpl::invoke).
    
    This change releases m_aMutex in 
CWinClipboard::handleClipboardContentChanged as
    soon as it in not needed anymore. This aligns with comment several lines 
above,
    telling that transferables must be destroyed only outside of the mutex lock.
    
    Change-Id: I9faf254930a8913d1621f5ed504aeb369b37adfc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179984
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/vcl/win/dtrans/WinClipboard.cxx b/vcl/win/dtrans/WinClipboard.cxx
index 6fb07aaa6bb4..0cc55a23b6f0 100644
--- a/vcl/win/dtrans/WinClipboard.cxx
+++ b/vcl/win/dtrans/WinClipboard.cxx
@@ -328,12 +328,13 @@ void CWinClipboard::handleClipboardContentChanged()
                                                             rXTransf);
         maClipboardListeners.notifyEach(
             aGuard, 
&datatransfer::clipboard::XClipboardListener::changedContents, aClipbEvent);
+        aGuard.unlock(); // for XTransferable dtor, that may delegate to 
another thread
     }
     catch (const lang::DisposedException&)
     {
         OSL_FAIL("Service Manager disposed");
-
-        aGuard.unlock();
+        if (aGuard.owns_lock())
+            aGuard.unlock();
         // no further clipboard changed notifications
         unregisterClipboardViewer();
     }

Reply via email to