diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2023-06-13 12:30:44 +0200 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2023-06-13 16:07:15 +0200 |
commit | 889c12e98e04edb4bc25b86bf16b8cf1d9b68420 (patch) | |
tree | e2a8d51b9d1bb4d65347cbff059e52659973e032 /vcl | |
parent | ac1099443e70eefbd8fdd7dd3705fff08a9c75b8 (diff) |
tdf#155794 vcl: handle WM_GETOBJECT without SolarMutex
SalFrameWndProc() handles WM_GETOBJECT by acquiring SolarMutex and
calling ImplHandleGetObject(), which again acquires the SolarMutex
inside Application::SetSettings().
This was introduced with commit db214684057e3ff2fa32d57c00507309dd6c24d6
due to thread-safety crashes but it turns out that it can be problematic.
When loading a document on a non-main thread, WinSalFrame::SetTitle()
calls SetWindowTextW which is equivalent to SendMessage(WM_SETTEXT),
while holding SolarMutex, and if the main thread doesn't finish
processing it then that's a deadlock.
Typically Desktop::Main() has already created the mxAccessBridge, so
ImplHandleGetObject() most likely doesn't need to do it, so just skip
the Settings code there in case the SolarMutex is locked by another
thread.
In case the SolarMutex is locked by another thread, do an unsafe read of
ImplGetSVData()->mxAccessBridge - this should work until ImplSVData is
deleted, by which time no Windows should exist anymore that could be
receiving messages.
This fixes part of the problem, winaccessibility also needs to stop
using SolarMutex.
Change-Id: I62b027ad06d2c3eb06a5f64b052a4acd0908f79c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152958
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/win/window/salframe.cxx | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx index e0a99d8e8779..2e60f38c1f11 100644 --- a/vcl/win/window/salframe.cxx +++ b/vcl/win/window/salframe.cxx @@ -5395,30 +5395,43 @@ static void ImplHandleIMENotify( HWND hWnd, WPARAM wParam ) static bool ImplHandleGetObject(HWND hWnd, LPARAM lParam, WPARAM wParam, LRESULT & nRet) { - if (!Application::GetSettings().GetMiscSettings().GetEnableATToolSupport()) + uno::Reference<accessibility::XMSAAService> xMSAA; + if (ImplSalYieldMutexTryToAcquire()) { - // IA2 should be enabled automatically - AllSettings aSettings = Application::GetSettings(); - MiscSettings aMisc = aSettings.GetMiscSettings(); - aMisc.SetEnableATToolSupport(true); - // The above is enough, since aMisc changes the same shared ImplMiscData as used in global - // settings, so no need to call aSettings.SetMiscSettings and Application::SetSettings - if (!Application::GetSettings().GetMiscSettings().GetEnableATToolSupport()) - return false; // locked down somehow ? - } + { + // IA2 should be enabled automatically + AllSettings aSettings = Application::GetSettings(); + MiscSettings aMisc = aSettings.GetMiscSettings(); + aMisc.SetEnableATToolSupport(true); + // The above is enough, since aMisc changes the same shared ImplMiscData as used in global + // settings, so no need to call aSettings.SetMiscSettings and Application::SetSettings + + if (!Application::GetSettings().GetMiscSettings().GetEnableATToolSupport()) + return false; // locked down somehow ? + } - ImplSVData* pSVData = ImplGetSVData(); + ImplSVData* pSVData = ImplGetSVData(); - // Make sure to launch Accessibility only the following criteria are satisfied - // to avoid RFT interrupts regular accessibility processing - if ( !pSVData->mxAccessBridge.is() ) - { - if( !InitAccessBridge() ) - return false; + // Make sure to launch Accessibility only the following criteria are satisfied + // to avoid RFT interrupts regular accessibility processing + if ( !pSVData->mxAccessBridge.is() ) + { + if( !InitAccessBridge() ) + return false; + } + xMSAA.set(pSVData->mxAccessBridge, uno::UNO_QUERY); + ImplSalYieldMutexRelease(); + } + else + { // tdf#155794: access without locking: hopefully this should be fine + // as the bridge is typically inited in Desktop::Main() already and the + // WM_GETOBJECT is received only on the main thread and by the time in + // VCL shutdown when ImplSvData dies there should not be Windows any + // more that could receive messages. + xMSAA.set(ImplGetSVData()->mxAccessBridge, uno::UNO_QUERY); } - uno::Reference< accessibility::XMSAAService > xMSAA( pSVData->mxAccessBridge, uno::UNO_QUERY ); if ( xMSAA.is() ) { sal_Int32 lParam32 = static_cast<sal_Int32>(lParam); @@ -5963,12 +5976,11 @@ static LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LP break; case WM_GETOBJECT: - ImplSalYieldMutexAcquireWithWait(); + // tdf#155794: this must complete without taking SolarMutex if ( ImplHandleGetObject( hWnd, lParam, wParam, nRet ) ) { rDef = false; } - ImplSalYieldMutexRelease(); break; case WM_APPCOMMAND: |