From 316447dd0284d79516cc313636e5857f542d6417 Mon Sep 17 00:00:00 2001 From: Jan-Marek Glogowski Date: Fri, 17 Aug 2018 19:41:53 +0200 Subject: tdf#118786 WIN allow nested SendMessage calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This bug trips "assert( !pInst->mbNoYieldLock )". There is already a special case, introduced in commit 4baec725e0dc ("WIN run main thread redirects ignoring SolarMutex"), to prevent tripping the assert for a nested SendMessage call. So this implements a general solution for nested SendMessage calls. We just have to prevent yielding in a call from an other thread, as the sending thread still owns the SolarMutex. This way we can also drop the special handling in WinSalFrame::ReleaseFrameGraphicsDC. Conflicts: vcl/win/app/salinst.cxx Change-Id: I7024b081b26f3545af12a3a3a038fe5e5671af3c Reviewed-on: https://gerrit.libreoffice.org/59275 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski (cherry picked from commit 35a254750392dcd738481f5d6e8719cee9fb41b3) Reviewed-on: https://gerrit.libreoffice.org/59318 Reviewed-by: Caolán McNamara Tested-by: Caolán McNamara (cherry picked from commit 3e392904c558d1f9fc91926511d148762813537e) Reviewed-on: https://gerrit.libreoffice.org/60725 Reviewed-by: Michael Stahl --- vcl/win/app/salinst.cxx | 41 +++++++++++++++++++++++++++++++++-------- vcl/win/window/salframe.cxx | 9 ++------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx index dcea8d53f6d7..f6e17bcf7faa 100644 --- a/vcl/win/app/salinst.cxx +++ b/vcl/win/app/salinst.cxx @@ -477,6 +477,11 @@ bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents ) bool bWasMsg = false, bOneEvent = false, bWasTimeoutMsg = false; ImplSVData *const pSVData = ImplGetSVData(); WinSalTimer* pTimer = static_cast( pSVData->maSchedCtx.mpSalTimer ); + const bool bNoYieldLock = GetSalData()->mpInstance->mbNoYieldLock; + + assert( !bNoYieldLock ); + if ( bNoYieldLock ) + return false; sal_uInt32 nCurTicks = 0; if ( bHandleAllCurrentEvents ) @@ -571,26 +576,46 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents) #define CASE_NOYIELDLOCK( salmsg, function ) \ case salmsg: \ - assert( !pInst->mbNoYieldLock ); \ - pInst->mbNoYieldLock = true; \ - function; \ - pInst->mbNoYieldLock = false; \ + if (bIsOtherThreadMessage) \ + { \ + assert( !pInst->mbNoYieldLock ); \ + pInst->mbNoYieldLock = true; \ + function; \ + pInst->mbNoYieldLock = false; \ + } \ + else \ + { \ + DBG_TESTSOLARMUTEX(); \ + function; \ + } \ break; #define CASE_NOYIELDLOCK_RESULT( salmsg, function ) \ case salmsg: \ - assert( !pInst->mbNoYieldLock ); \ - pInst->mbNoYieldLock = true; \ - nRet = reinterpret_cast( function ); \ - pInst->mbNoYieldLock = false; \ + if (bIsOtherThreadMessage) \ + { \ + assert( !pInst->mbNoYieldLock ); \ + pInst->mbNoYieldLock = true; \ + nRet = reinterpret_cast( function ); \ + pInst->mbNoYieldLock = false; \ + } \ + else \ + { \ + DBG_TESTSOLARMUTEX(); \ + nRet = reinterpret_cast( function ); \ + } \ break; LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, bool& rDef ) { + const BOOL bIsOtherThreadMessage = InSendMessage(); LRESULT nRet = 0; WinSalInstance *pInst = GetSalData()->mpInstance; WinSalTimer *const pTimer = static_cast( ImplGetSVData()->maSchedCtx.mpSalTimer ); + SAL_INFO("vcl.gdi.wndproc", "SalComWndProc(nMsg=" << nMsg << ", wParam=" << wParam + << ", lParam=" << lParam << "); inSendMsg: " << bIsOtherThreadMessage); + switch ( nMsg ) { case SAL_MSG_THREADYIELD: diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx index f34c9d0936cc..27081ed647bd 100644 --- a/vcl/win/window/salframe.cxx +++ b/vcl/win/window/salframe.cxx @@ -921,13 +921,8 @@ bool WinSalFrame::ReleaseFrameGraphicsDC( WinSalGraphics* pGraphics ) if ( pGraphics->getDefPal() ) SelectPalette( hDC, pGraphics->getDefPal(), TRUE ); pGraphics->DeInitGraphics(); - // we don't want to run the WinProc in the main thread directly - // so we don't hit the mbNoYieldLock assert - if ( !pSalData->mpInstance->IsMainThread() ) - SendMessageW( pSalData->mpInstance->mhComWnd, SAL_MSG_RELEASEDC, - reinterpret_cast(mhWnd), reinterpret_cast(hDC) ); - else - ReleaseDC( mhWnd, hDC ); + SendMessageW( pSalData->mpInstance->mhComWnd, SAL_MSG_RELEASEDC, + reinterpret_cast(mhWnd), reinterpret_cast(hDC) ); if ( pGraphics == mpThreadGraphics ) pSalData->mnCacheDCInUse--; pGraphics->setHDC(nullptr); -- cgit