summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vcl/svapp.hxx8
-rw-r--r--vcl/README.scheduler25
-rw-r--r--vcl/headless/svpinst.cxx5
-rw-r--r--vcl/inc/headless/svpinst.hxx2
-rw-r--r--vcl/inc/osx/salinst.h3
-rw-r--r--vcl/inc/salinst.hxx2
-rw-r--r--vcl/inc/unx/gtk/gtkinst.hxx2
-rw-r--r--vcl/inc/unx/salinst.h2
-rw-r--r--vcl/inc/win/salinst.h5
-rw-r--r--vcl/osx/salinst.cxx4
-rw-r--r--vcl/qa/cppunit/timer.cxx2
-rw-r--r--vcl/source/app/svapp.cxx34
-rw-r--r--vcl/unx/generic/app/salinst.cxx4
-rw-r--r--vcl/unx/gtk/gtkinst.cxx4
-rw-r--r--vcl/win/app/salinst.cxx124
-rw-r--r--vcl/win/window/salframe.cxx13
16 files changed, 139 insertions, 100 deletions
diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index 89a375ca9e4f..3e3938498b75 100644
--- a/include/vcl/svapp.hxx
+++ b/include/vcl/svapp.hxx
@@ -495,12 +495,6 @@ public:
*/
static void EndYield();
- /** Acquire SolarMutex after it has been temporarily dropped completely.
-
- This will Reschedule() on WNT and just acquire on other platforms.
- */
- static void ReAcquireSolarMutex(sal_uLong nReleased);
-
/** @brief Get the Solar Mutex for this thread.
Get the Solar Mutex that prevents other threads from accessing VCL
@@ -1481,7 +1475,7 @@ class SolarMutexReleaser
const sal_uInt32 mnReleased;
public:
SolarMutexReleaser(): mnReleased(Application::ReleaseSolarMutex()) {}
- ~SolarMutexReleaser() { Application::ReAcquireSolarMutex(mnReleased); }
+ ~SolarMutexReleaser() { Application::AcquireSolarMutex( mnReleased ); }
};
VCL_DLLPUBLIC Application* GetpApp();
diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index 05684cef8150..a7d2cbb04682 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -89,6 +89,21 @@ can be added to the scheduler reasonably.
= Implementation details =
+== General: main thread deferral ==
+
+Currently for Mac and Windows, we run main thread deferrals by disabling the
+SolarMutex using a boolean. In the case of the redirect, this makes
+tryToaAcquire and doAcquire return true or 1, while a release is ignored.
+Also the IsCurrentThread() mutex check function will act accordingly, so all
+the DBG_TESTSOLARMUTEX won't fail.
+
+Since we just disable the locks when we start running the deferred code in the
+main thread, we won't let the main thread run into stuff, where it would
+normally wait for the SolarMutex.
+
+Eventually this will move into the GenericSolarMutex. KDE / Qt also does main
+thread redirects using Qt::BlockingQueuedConnection.
+
== MacOS implementation details ==
Generally the Scheduler is handled as expected, except on resize, which is
@@ -100,9 +115,9 @@ Like the Windows backend, all Cocoa / GUI handling also has to be run in
the main thread. We're emulating Windows out-of-order PeekMessage processing,
via a YieldWakeupEvent and two conditionals. When in a RUNINMAIN call, all
the DBG_TESTSOLARMUTEX calls are disabled, as we can't release the SolarMutex,
-but we can prevent running any other SolarMutex based code. Same for all the
-SolarMutex acquire and release calls, so the calling and the main thread
-don't deadlock. Those wakeup events must be ignored to prevent busy-locks.
+but we can prevent running any other SolarMutex based code. Those wakeup
+events must be ignored to prevent busy-locks. For more info read the "General:
+main thread deferral" section.
We can neither rely on MacOS dispatch_sync code block execution nor the
message handling, as both can't be prioritized or filtered and the first
@@ -136,6 +151,10 @@ the timer callback message, which is checked before starting the Scheduler.
This way we can end with multiple timer callback message in the queue, which
we were asserting.
+To run the required GUI code in the main thread without unlocking the
+SolarMutex, we "disable" it. For more infos read the "General: main thread
+deferral" section.
+
== KDE implementation details ==
This implementation also works as intended. But there is a different Yield
diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index d64d944a8802..302405f8f59d 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -304,12 +304,9 @@ SalBitmap* SvpSalInstance::CreateSalBitmap()
#endif
}
-bool SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
+bool SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
{
- (void) nReleased;
- assert(nReleased == 0); // not implemented
// first, check for already queued events.
-
std::list< SalUserEvent > aEvents;
{
osl::MutexGuard g(m_aEventGuard);
diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx
index e8bb96ab68ac..0883981c4406 100644
--- a/vcl/inc/headless/svpinst.hxx
+++ b/vcl/inc/headless/svpinst.hxx
@@ -155,7 +155,7 @@ public:
// wait next event and dispatch
// must returned by UserEvent (SalFrame::PostEvent)
// and timer
- virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) override;
+ virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents) override;
virtual bool AnyInput( VclInputFlags nType ) override;
virtual bool IsMainThread() const override { return true; }
diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 1f456f737901..65db0d0b0f2a 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -114,8 +114,7 @@ public:
virtual comphelper::SolarMutex* GetYieldMutex() override;
virtual sal_uInt32 ReleaseYieldMutex( bool bUnlockAll = false ) override;
virtual void AcquireYieldMutex( sal_uInt32 nCount = 1 ) override;
- virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents,
- sal_uLong nReleased) override;
+ virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents) override;
virtual bool AnyInput( VclInputFlags nType ) override;
virtual SalMenu* CreateMenu( bool bMenuBar, Menu* pVCLMenu ) override;
virtual void DestroyMenu( SalMenu* ) override;
diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx
index 12959cc44280..8418a1ed8126 100644
--- a/vcl/inc/salinst.hxx
+++ b/vcl/inc/salinst.hxx
@@ -133,7 +133,7 @@ public:
* If bHandleAllCurrentEvents - dispatch multiple posted
* user events. Returns true if events were processed.
*/
- virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) = 0;
+ virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents) = 0;
virtual bool AnyInput( VclInputFlags nType ) = 0;
// menus
diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx
index 1585c778afac..595a7adb7089 100644
--- a/vcl/inc/unx/gtk/gtkinst.hxx
+++ b/vcl/inc/unx/gtk/gtkinst.hxx
@@ -208,7 +208,7 @@ public:
const SystemGraphicsData* = nullptr ) override;
virtual SalBitmap* CreateSalBitmap() override;
- virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) override;
+ virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents) override;
virtual bool AnyInput( VclInputFlags nType ) override;
// impossible to handle correctly, as "main thread" depends on the dispatch mutex
virtual bool IsMainThread() const override { return false; }
diff --git a/vcl/inc/unx/salinst.h b/vcl/inc/unx/salinst.h
index 2307410fe69e..59464b4c60e5 100644
--- a/vcl/inc/unx/salinst.h
+++ b/vcl/inc/unx/salinst.h
@@ -74,7 +74,7 @@ public:
virtual SalSession* CreateSalSession() override;
virtual OpenGLContext* CreateOpenGLContext() override;
- virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) override;
+ virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents) override;
virtual bool AnyInput( VclInputFlags nType ) override;
virtual bool IsMainThread() const override { return true; }
diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h
index 6efecbd6bd5e..8772ee00fa22 100644
--- a/vcl/inc/win/salinst.h
+++ b/vcl/inc/win/salinst.h
@@ -34,6 +34,9 @@ public:
/// The Yield mutex ensures that only one thread calls into VCL
SalYieldMutex* mpSalYieldMutex;
+ osl::Condition maWaitingYieldCond;
+ bool mbNoYieldLock;
+
public:
WinSalInstance();
virtual ~WinSalInstance() override;
@@ -63,7 +66,7 @@ public:
virtual void AcquireYieldMutex( sal_uInt32 nCount = 1 ) override;
virtual bool IsMainThread() const override;
- virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) override;
+ virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents) override;
virtual bool AnyInput( VclInputFlags nType ) override;
virtual SalMenu* CreateMenu( bool bMenuBar, Menu* ) override;
virtual void DestroyMenu( SalMenu* ) override;
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 54f6ffdd7021..947e484b5c1d 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -533,10 +533,8 @@ SAL_WNODEPRECATED_DECLARATIONS_PUSH
SAL_WNODEPRECATED_DECLARATIONS_POP
}
-bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
+bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
{
- (void) nReleased;
- assert(nReleased == 0); // not implemented
bool bHadEvent = false;
// ensure that the per thread autorelease pool is top level and
diff --git a/vcl/qa/cppunit/timer.cxx b/vcl/qa/cppunit/timer.cxx
index 28f4284f1430..7b712bd76c04 100644
--- a/vcl/qa/cppunit/timer.cxx
+++ b/vcl/qa/cppunit/timer.cxx
@@ -148,7 +148,7 @@ void TimerTest::testIdleMainloop()
// can't test this via Application::Yield since this
// also processes all tasks directly via the scheduler.
pSVData->maAppData.mnDispatchLevel++;
- pSVData->mpDefInst->DoYield(true, false, 0);
+ pSVData->mpDefInst->DoYield(true, false);
pSVData->maAppData.mnDispatchLevel--;
}
CPPUNIT_ASSERT_MESSAGE("mainloop idle triggered", bTriggered);
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 3107e88d3c91..612fce86bc2f 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -451,12 +451,12 @@ void Application::Execute()
pSVData->maAppData.mbInAppExecute = false;
}
-inline bool ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased)
+inline bool ImplYield(bool i_bWait, bool i_bAllEvents)
{
ImplSVData* pSVData = ImplGetSVData();
SAL_INFO("vcl.schedule", "Enter ImplYield: " << (i_bWait ? "wait" : "no wait") <<
- ": " << (i_bAllEvents ? "all events" : "one event") << ": " << nReleased);
+ ": " << (i_bAllEvents ? "all events" : "one event"));
// TODO: there's a data race here on WNT only because ImplYield may be
// called without SolarMutex; if we can get rid of LazyDelete (with VclPtr)
@@ -466,10 +466,8 @@ inline bool ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased
// do not wait for events if application was already quit; in that
// case only dispatch events already available
- bool bProcessedEvent =
- pSVData->mpDefInst->DoYield(
- i_bWait && !pSVData->maAppData.mbAppQuit,
- i_bAllEvents, nReleased);
+ bool bProcessedEvent = pSVData->mpDefInst->DoYield(
+ i_bWait && !pSVData->maAppData.mbAppQuit, i_bAllEvents );
pSVData->maAppData.mnDispatchLevel--;
@@ -485,7 +483,7 @@ inline bool ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased
bool Application::Reschedule( bool i_bAllEvents )
{
- return ImplYield(false, i_bAllEvents, 0);
+ return ImplYield(false, i_bAllEvents);
}
void Scheduler::ProcessEventsToSignal(bool& bSignal)
@@ -537,27 +535,7 @@ SAL_DLLPUBLIC_EXPORT void unit_lok_process_events_to_idle()
void Application::Yield()
{
- ImplYield(true, false, 0);
-}
-
-void Application::ReAcquireSolarMutex(sal_uLong const nReleased)
-{
- // 0 would mean that events/timers will be handled without locking
- // SolarMutex (racy)
- SAL_WARN_IF(nReleased == 0, "vcl", "SolarMutexReleaser without SolarMutex");
-#ifdef _WIN32
- if (nReleased == 0 || ImplGetSVData()->mbDeInit) //do not Yield in DeInitVCL
- AcquireSolarMutex(nReleased);
- else
- ImplYield(false, false, nReleased);
-#else
- // a) Yield is not needed on non-WNT platforms
- // b) some Yield implementations for X11 (e.g. kde4) make it non-obvious
- // how to use nReleased
- // c) would require a review of what all Yield implementations do
- // currently _before_ releasing SolarMutex that would run without lock
- AcquireSolarMutex(nReleased);
-#endif
+ ImplYield(true, false);
}
IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplQuitMsg, void*, void )
diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx
index 98d56c6cd86e..e38164ee247b 100644
--- a/vcl/unx/generic/app/salinst.cxx
+++ b/vcl/unx/generic/app/salinst.cxx
@@ -166,10 +166,8 @@ bool X11SalInstance::AnyInput(VclInputFlags nType)
return bRet;
}
-bool X11SalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
+bool X11SalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
{
- (void) nReleased;
- assert(nReleased == 0); // not implemented
return mpXLib->Yield( bWait, bHandleAllCurrentEvents );
}
diff --git a/vcl/unx/gtk/gtkinst.cxx b/vcl/unx/gtk/gtkinst.cxx
index 2cd8b11c44d1..bc6fe03c9c2d 100644
--- a/vcl/unx/gtk/gtkinst.cxx
+++ b/vcl/unx/gtk/gtkinst.cxx
@@ -411,10 +411,8 @@ void GtkInstance::RemoveTimer ()
m_pTimer = nullptr;
}
-bool GtkInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
+bool GtkInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
{
- (void) nReleased;
- assert(nReleased == 0); // not implemented
EnsureInit();
return GetGtkSalData()->Yield( bWait, bHandleAllCurrentEvents );
}
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index 92ed7faa14fd..be96ed17c654 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -112,6 +112,7 @@ public:
explicit SalYieldMutex();
virtual bool IsCurrentThread() const override;
+ virtual bool tryToAcquire() override;
};
SalYieldMutex::SalYieldMutex()
@@ -139,6 +140,8 @@ void SalYieldMutex::doAcquire( sal_uInt32 nLockCount )
WinSalInstance* pInst = GetSalData()->mpFirstInstance;
if ( pInst && pInst->IsMainThread() )
{
+ if ( pInst->mbNoYieldLock )
+ return;
// tdf#96887 If this is the main thread, then we must wait for two things:
// - the mpSalYieldMutex being freed
// - SendMessage() being triggered
@@ -167,15 +170,31 @@ void SalYieldMutex::doAcquire( sal_uInt32 nLockCount )
sal_uInt32 SalYieldMutex::doRelease( const bool bUnlockAll )
{
- sal_uInt32 nCount = comphelper::GenericSolarMutex::doRelease( bUnlockAll );
+ WinSalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( pInst && pInst->mbNoYieldLock && pInst->IsMainThread() )
+ return 1;
+ sal_uInt32 nCount = comphelper::GenericSolarMutex::doRelease( bUnlockAll );
// wake up ImplSalYieldMutexAcquireWithWait() after release
if ( 0 == m_nCount )
m_condition.set();
-
return nCount;
}
+bool SalYieldMutex::tryToAcquire()
+{
+ WinSalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( pInst )
+ {
+ if ( pInst->mbNoYieldLock && pInst->IsMainThread() )
+ return true;
+ else
+ return comphelper::GenericSolarMutex::tryToAcquire();
+ }
+ else
+ return false;
+}
+
void ImplSalYieldMutexAcquireWithWait( sal_uInt32 nCount )
{
WinSalInstance* pInst = GetSalData()->mpFirstInstance;
@@ -186,10 +205,7 @@ void ImplSalYieldMutexAcquireWithWait( sal_uInt32 nCount )
bool ImplSalYieldMutexTryToAcquire()
{
WinSalInstance* pInst = GetSalData()->mpFirstInstance;
- if ( pInst )
- return pInst->mpSalYieldMutex->tryToAcquire();
- else
- return false;
+ return pInst ? pInst->mpSalYieldMutex->tryToAcquire() : false;
}
void ImplSalYieldMutexRelease()
@@ -204,8 +220,11 @@ void ImplSalYieldMutexRelease()
bool SalYieldMutex::IsCurrentThread() const
{
- // For the Windows backend, the LO identifier is the system thread ID
- return m_nThreadId == GetCurrentThreadId();
+ if ( !GetSalData()->mpFirstInstance->mbNoYieldLock )
+ // For the Windows backend, the LO identifier is the system thread ID
+ return m_nThreadId == GetCurrentThreadId();
+ else
+ return GetSalData()->mpFirstInstance->IsMainThread();
}
void SalData::initKeyCodeMap()
@@ -443,9 +462,10 @@ void DestroySalInstance( SalInstance* pInst )
}
WinSalInstance::WinSalInstance()
+ : mhComWnd( nullptr )
+ , mbNoYieldLock( false )
{
- mhComWnd = nullptr;
- mpSalYieldMutex = new SalYieldMutex();
+ mpSalYieldMutex = new SalYieldMutex();
mpSalYieldMutex->acquire();
}
@@ -484,8 +504,7 @@ static void ImplSalDispatchMessage( MSG* pMsg )
ImplSalPostDispatchMsg( pMsg, lResult );
}
-bool
-ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
+static bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
{
MSG aMsg;
bool bWasMsg = false, bOneEvent = false;
@@ -535,38 +554,44 @@ bool WinSalInstance::IsMainThread() const
return pSalData->mnAppThreadId == GetCurrentThreadId();
}
-bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
+bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
{
bool bDidWork = false;
- // NOTE: if nReleased != 0 this will be called without SolarMutex
- // so don't do anything dangerous before releasing it here
- sal_uInt32 const nCount = (nReleased != 0)
- ? nReleased : mpSalYieldMutex->release( true );
+ SolarMutexReleaser aReleaser;
if ( !IsMainThread() )
{
- // #97739# A SendMessage call blocks until the called thread (here: the main thread)
- // returns. During a yield however, messages are processed in the main thread that might
- // result in a new message loop due to opening a dialog. Thus, SendMessage would not
- // return which will block this thread!
- // Solution: just give up the time slice and hope that messages are processed
- // by the main thread anyway (where all windows are created)
- // If the mainthread is not currently handling messages, then our SendMessage would
- // also do nothing, so this seems to be reasonable.
-
- // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
- if( ImplGetSVData()->maAppData.mnModalMode )
- Sleep(1);
- else
- // If you change the SendMessageW function, you might need to update
- // the PeekMessage( ... PM_QS_POSTMESSAGE) calls!
- bDidWork = SendMessageW( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
+ if ( bWait )
+ {
+ maWaitingYieldCond.reset();
+ maWaitingYieldCond.wait();
+ bDidWork = true;
+ }
+ else {
+ // #97739# A SendMessage call blocks until the called thread (here: the main thread)
+ // returns. During a yield however, messages are processed in the main thread that might
+ // result in a new message loop due to opening a dialog. Thus, SendMessage would not
+ // return which will block this thread!
+ // Solution: just give up the time slice and hope that messages are processed
+ // by the main thread anyway (where all windows are created)
+ // If the mainthread is not currently handling messages, then our SendMessage would
+ // also do nothing, so this seems to be reasonable.
+
+ // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
+ if( ImplGetSVData()->maAppData.mnModalMode )
+ Sleep(1);
+ else
+ // If you change the SendMessageW function, you might need to update
+ // the PeekMessage( ... PM_QS_POSTMESSAGE) calls!
+ bDidWork = SendMessageW( mhComWnd, SAL_MSG_THREADYIELD,
+ (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
+ }
}
else
{
- if (nReleased == 0) // tdf#99383 ReAcquireSolarMutex shouldn't Yield
- bDidWork = ImplSalYield( bWait, bHandleAllCurrentEvents );
+ bDidWork = ImplSalYield( bWait, bHandleAllCurrentEvents );
+ if ( bDidWork )
+ maWaitingYieldCond.set();
}
- mpSalYieldMutex->acquire( nCount );
return bDidWork;
}
@@ -574,6 +599,7 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong
LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
{
LRESULT nRet = 0;
+ WinSalInstance *pInst = GetSalData()->mpFirstInstance;
switch ( nMsg )
{
@@ -596,19 +622,31 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i
static_cast<WinSalTimer*>(ImplGetSVData()->maSchedCtx.mpSalTimer)->ImplStop();
break;
case SAL_MSG_CREATEFRAME:
+ assert( !pInst->mbNoYieldLock );
+ pInst->mbNoYieldLock = true;
nRet = reinterpret_cast<LRESULT>(ImplSalCreateFrame( GetSalData()->mpFirstInstance, reinterpret_cast<HWND>(lParam), (SalFrameStyleFlags)wParam ));
+ pInst->mbNoYieldLock = false;
rDef = FALSE;
break;
case SAL_MSG_RECREATEHWND:
+ assert( !pInst->mbNoYieldLock );
+ pInst->mbNoYieldLock = true;
nRet = reinterpret_cast<LRESULT>(ImplSalReCreateHWND( reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), false ));
+ pInst->mbNoYieldLock = false;
rDef = FALSE;
break;
case SAL_MSG_RECREATECHILDHWND:
+ assert( !pInst->mbNoYieldLock );
+ pInst->mbNoYieldLock = true;
nRet = reinterpret_cast<LRESULT>(ImplSalReCreateHWND( reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), true ));
+ pInst->mbNoYieldLock = false;
rDef = FALSE;
break;
case SAL_MSG_DESTROYFRAME:
+ assert( !pInst->mbNoYieldLock );
+ pInst->mbNoYieldLock = true;
delete reinterpret_cast<SalFrame*>(lParam);
+ pInst->mbNoYieldLock = false;
rDef = FALSE;
break;
case SAL_MSG_DESTROYHWND:
@@ -624,19 +662,31 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i
rDef = FALSE;
break;
case SAL_MSG_CREATEOBJECT:
+ assert( !pInst->mbNoYieldLock );
+ pInst->mbNoYieldLock = true;
nRet = reinterpret_cast<LRESULT>(ImplSalCreateObject( GetSalData()->mpFirstInstance, reinterpret_cast<WinSalFrame*>(lParam) ));
+ pInst->mbNoYieldLock = false;
rDef = FALSE;
break;
case SAL_MSG_DESTROYOBJECT:
+ assert( !pInst->mbNoYieldLock );
+ pInst->mbNoYieldLock = true;
delete reinterpret_cast<SalObject*>(lParam);
+ pInst->mbNoYieldLock = false;
rDef = FALSE;
break;
case SAL_MSG_GETDC:
+ assert( !pInst->mbNoYieldLock );
+ pInst->mbNoYieldLock = true;
nRet = reinterpret_cast<LRESULT>(GetDCEx( reinterpret_cast<HWND>(wParam), nullptr, DCX_CACHE ));
+ pInst->mbNoYieldLock = false;
rDef = FALSE;
break;
case SAL_MSG_RELEASEDC:
+ assert( !pInst->mbNoYieldLock );
+ pInst->mbNoYieldLock = true;
ReleaseDC( reinterpret_cast<HWND>(wParam), reinterpret_cast<HDC>(lParam) );
+ pInst->mbNoYieldLock = false;
rDef = FALSE;
break;
case SAL_MSG_TIMER_CALLBACK:
@@ -646,7 +696,7 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i
MSG aMsg;
bool bValidMSG = pTimer->IsValidWPARAM( wParam );
// PM_QS_POSTMESSAGE is needed, so we don't process the SendMessage from DoYield!
- while ( PeekMessageW(&aMsg, GetSalData()->mpFirstInstance->mhComWnd, SAL_MSG_TIMER_CALLBACK,
+ while ( PeekMessageW(&aMsg, pInst->mhComWnd, SAL_MSG_TIMER_CALLBACK,
SAL_MSG_TIMER_CALLBACK, PM_REMOVE | PM_NOYIELD | PM_QS_POSTMESSAGE) )
{
assert( !bValidMSG && "Unexpected non-last valid message" );
diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx
index e2c444a3e182..8a9c6066c461 100644
--- a/vcl/win/window/salframe.cxx
+++ b/vcl/win/window/salframe.cxx
@@ -1054,10 +1054,15 @@ void WinSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
if ( mpGraphics2->getDefPal() )
SelectPalette( mpGraphics2->getHDC(), mpGraphics2->getDefPal(), TRUE );
mpGraphics2->DeInitGraphics();
- SendMessageW( pSalData->mpFirstInstance->mhComWnd,
- SAL_MSG_RELEASEDC,
- reinterpret_cast<WPARAM>(mhWnd),
- reinterpret_cast<LPARAM>(mpGraphics2->getHDC()) );
+ // we don't want to run the WinProc in the main thread directly
+ // so we don't hit the mbNoYieldLock assert
+ if ( !pSalData->mpFirstInstance->IsMainThread() )
+ SendMessageW( pSalData->mpFirstInstance->mhComWnd,
+ SAL_MSG_RELEASEDC,
+ reinterpret_cast<WPARAM>(mhWnd),
+ reinterpret_cast<LPARAM>(mpGraphics2->getHDC()) );
+ else
+ ReleaseDC( mhWnd, mpGraphics2->getHDC() );
mpGraphics2->setHDC(nullptr);
pSalData->mnCacheDCInUse--;
}