diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2021-11-17 10:29:24 +0100 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2022-01-21 12:42:20 +0100 |
commit | a9bb94e28a6757719a2e833c9d3ca17b3205283b (patch) | |
tree | 23e68d198a5fc609bfbb5567b0be90f2f4638935 | |
parent | 3eb6d764b3023500f2299d36bf1860bc8e67db9f (diff) |
VCL fix shutdown when run via system loop
Adds DoQuit and SAL_USE_SYSTEM_LOOP to complement DoExecute.
Makes it easier to switch between a LO with and without nested
event processing. Unfortunatly the recovery dialogs run outside
of Application::Execute(), so this currently also disables
recovery handling.
Follow-up (and no more Emscripten-specific) change to commit
93133585b5b52e38defc3162eeb1e7704dceafcb ("WASM optionally run
any app via system loop").
Change-Id: I1b622065d7fa0c5ad03a7c7daaf8241dcc3f09a3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128717
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
-rw-r--r-- | desktop/source/app/app.cxx | 1 | ||||
-rw-r--r-- | include/vcl/svapp.hxx | 6 | ||||
-rw-r--r-- | vcl/README.vars.md | 1 | ||||
-rw-r--r-- | vcl/inc/qt5/QtInstance.hxx | 1 | ||||
-rw-r--r-- | vcl/inc/salinst.hxx | 4 | ||||
-rw-r--r-- | vcl/inc/svdata.hxx | 2 | ||||
-rw-r--r-- | vcl/qt5/QtInstance.cxx | 19 | ||||
-rw-r--r-- | vcl/qt5/QtTimer.cxx | 11 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 14 | ||||
-rw-r--r-- | vcl/source/app/svapp.cxx | 38 | ||||
-rw-r--r-- | vcl/source/app/svdata.cxx | 7 |
11 files changed, 77 insertions, 27 deletions
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index b14c0d94299a..ada608229f8b 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -2020,6 +2020,7 @@ void Desktop::OpenClients() bool bExistsSessionData = false; bool const bDisableRecovery = getenv("OOO_DISABLE_RECOVERY") != nullptr + || IsOnSystemEventLoop() || !officecfg::Office::Recovery::RecoveryInfo::Enabled::get(); impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData); diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx index f4d065f1d664..137177bbfbb0 100644 --- a/include/vcl/svapp.hxx +++ b/include/vcl/svapp.hxx @@ -1323,6 +1323,12 @@ public: */ static void EndAllPopups(); + /** Returns true, if the VCL plugin runs on the system event loop. + * + * AKA the VCL plugin can't handle nested event loops, like WASM or mobile. + */ + static bool IsOnSystemEventLoop(); + ///@} // For vclbootstrapprotector: diff --git a/vcl/README.vars.md b/vcl/README.vars.md index c7971b734be0..c83ca657ef9f 100644 --- a/vcl/README.vars.md +++ b/vcl/README.vars.md @@ -9,6 +9,7 @@ These are the general environment variables used in the VCL: * `SAL_NO_NWF` - disable native widgets * `SAL_FORCEDPI` - force a specific DPI (gtk3 & qt5/kf5 plugins only) * `SAL_FORCE_HC` - force high-contrast mode +* `SAL_USE_SYSTEM_LOOP` - calls std::abort on nested event loop calls. Currently just for Qt with many crashes. WIP. * `SAL_NO_FONT_LOOKUP` - disable font search and fallback and always use a hard-coded font name (for some unit tests) diff --git a/vcl/inc/qt5/QtInstance.hxx b/vcl/inc/qt5/QtInstance.hxx index 9c3adb25e98b..2d246c0bd92d 100644 --- a/vcl/inc/qt5/QtInstance.hxx +++ b/vcl/inc/qt5/QtInstance.hxx @@ -176,6 +176,7 @@ public: void* CreateGStreamerSink(const SystemChildWindow*) override; bool DoExecute(int& nExitCode) override; + void DoQuit() override; }; inline QtInstance* GetQtInstance() { return static_cast<QtInstance*>(GetSalInstance()); } diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx index 90367c06bcc9..084ab2e51c58 100644 --- a/vcl/inc/salinst.hxx +++ b/vcl/inc/salinst.hxx @@ -215,7 +215,9 @@ public: // Note: we cannot make this a global variable, because it might be initialised BEFORE the putenv() call in cppunittester. static bool IsRunningUnitTest() { return getenv("LO_TESTNAME") != nullptr; } - virtual bool DoExecute(int & /* nExitCode */) { return false; } + // both must to be implemented, if the VCL plugin needs to run via system event loop + virtual bool DoExecute(int &nExitCode); + virtual void DoQuit(); }; // called from SVMain diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx index 89e4d67a3800..ae6e361cb079 100644 --- a/vcl/inc/svdata.hxx +++ b/vcl/inc/svdata.hxx @@ -133,6 +133,7 @@ typedef std::pair<VclPtr<vcl::Window>, ImplPostEventData *> ImplPostEventPair; struct ImplSVAppData { + ImplSVAppData(); ~ImplSVAppData(); std::optional<AllSettings> mxSettings; // Application settings @@ -159,6 +160,7 @@ struct ImplSVAppData bool mbSettingsInit = false; // true: Settings are initialized DialogCancelMode meDialogCancel = DialogCancelMode::Off; // true: All Dialog::Execute() calls will be terminated immediately with return false bool mbRenderToBitmaps = false; // set via svp / headless plugin + bool m_bUseSystemLoop = false; SvFileStream* mpEventTestInput = nullptr; Idle* mpEventTestingIdle = nullptr; diff --git a/vcl/qt5/QtInstance.cxx b/vcl/qt5/QtInstance.cxx index a03b71e46bd2..a52f6529c3bc 100644 --- a/vcl/qt5/QtInstance.cxx +++ b/vcl/qt5/QtInstance.cxx @@ -259,6 +259,8 @@ QtInstance::QtInstance(std::unique_ptr<QApplication>& pQApp, bool bUseCairo) #ifndef EMSCRIPTEN m_bSupportsOpenGL = true; +#else + ImplGetSVData()->maAppData.m_bUseSystemLoop = true; #endif } @@ -726,13 +728,16 @@ std::unique_ptr<QApplication> QtInstance::CreateQApplication(int& nArgc, char** bool QtInstance::DoExecute(int& nExitCode) { -#ifdef EMSCRIPTEN - nExitCode = m_pQApplication->exec(); - return true; -#else - (void)nExitCode; - return false; -#endif + const bool bIsOnSystemEventLoop = Application::IsOnSystemEventLoop(); + if (bIsOnSystemEventLoop) + nExitCode = QApplication::exec(); + return bIsOnSystemEventLoop; +} + +void QtInstance::DoQuit() +{ + if (Application::IsOnSystemEventLoop()) + QApplication::quit(); } extern "C" { diff --git a/vcl/qt5/QtTimer.cxx b/vcl/qt5/QtTimer.cxx index 6568ca8ac1b8..1a34213977dc 100644 --- a/vcl/qt5/QtTimer.cxx +++ b/vcl/qt5/QtTimer.cxx @@ -42,11 +42,12 @@ QtTimer::QtTimer() void QtTimer::timeoutActivated() { SolarMutexGuard aGuard; -#ifdef EMSCRIPTEN - const ImplSVData* pSVData = ImplGetSVData(); - assert(pSVData->mpDefInst); - static_cast<QtInstance*>(pSVData->mpDefInst)->DispatchUserEvents(true); -#endif + if (Application::IsOnSystemEventLoop()) + { + const ImplSVData* pSVData = ImplGetSVData(); + assert(pSVData && pSVData->mpDefInst); + static_cast<QtInstance*>(pSVData->mpDefInst)->DispatchUserEvents(true); + } CallCallback(); } diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index e19d055b8253..bfcd6834caac 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -142,6 +142,20 @@ bool SalInstance::CallEventCallback(void const* pEvent, int nBytes) return m_pEventInst.is() && m_pEventInst->dispatchEvent(pEvent, nBytes); } +bool SalInstance::DoExecute(int&) +{ + // can't run on system event loop without implementing DoExecute and DoQuit + if (Application::IsOnSystemEventLoop()) + std::abort(); + return false; +} + +void SalInstance::DoQuit() +{ + if (Application::IsOnSystemEventLoop()) + std::abort(); +} + SalTimer::~SalTimer() COVERITY_NOEXCEPT_FALSE {} void SalBitmap::DropScaledCache() diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index c1f3b4a5bccf..cc046decdad5 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -443,6 +443,11 @@ void Application::Execute() int nExitCode = 0; if (!pSVData->mpDefInst->DoExecute(nExitCode)) { + if (Application::IsOnSystemEventLoop()) + { + SAL_WARN("vcl.schedule", "Can't omit DoExecute when running on system event loop!"); + std::abort(); + } while (!pSVData->maAppData.mbAppQuit) Application::Yield(); } @@ -452,7 +457,6 @@ void Application::Execute() GetpApp()->Shutdown(); } -#ifndef EMSCRIPTEN static bool ImplYield(bool i_bWait, bool i_bAllEvents) { ImplSVData* pSVData = ImplGetSVData(); @@ -477,23 +481,27 @@ static bool ImplYield(bool i_bWait, bool i_bAllEvents) SAL_INFO("vcl.schedule", "Leave ImplYield with return " << bProcessedEvent ); return bProcessedEvent; } -#endif bool Application::Reschedule( bool i_bAllEvents ) { -#ifdef EMSCRIPTEN - SAL_WARN("wasm", "Application::Reschedule(" << i_bAllEvents << ")"); - (void) i_bAllEvents; - std::abort(); -#else + static const bool bAbort = Application::IsOnSystemEventLoop(); + if (bAbort) + { + SAL_WARN("vcl.schedule", "Application::Reschedule(" << i_bAllEvents << ")"); + std::abort(); + } return ImplYield(false, i_bAllEvents); -#endif +} + +bool Application::IsOnSystemEventLoop() +{ + return ImplGetSVData()->maAppData.m_bUseSystemLoop; } void Scheduler::ProcessEventsToIdle() { int nSanity = 1; - while( Application::Reschedule( true ) ) + while (ImplYield(false, true)) { if (0 == ++nSanity % 1000) { @@ -541,17 +549,19 @@ SAL_DLLPUBLIC_EXPORT void unit_lok_process_events_to_idle() void Application::Yield() { -#ifdef EMSCRIPTEN - SAL_WARN("wasm", "Application::Yield()"); - std::abort(); -#else + static const bool bAbort = Application::IsOnSystemEventLoop(); + if (bAbort) + { + SAL_WARN("vcl.schedule", "Application::Yield()"); + std::abort(); + } ImplYield(true, false); -#endif } IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplQuitMsg, void*, void ) { assert(ImplGetSVData()->maAppData.mbAppQuit); + ImplGetSVData()->mpDefInst->DoQuit(); } void Application::Quit() diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx index f91e1fe67fa9..7ba785277c3e 100644 --- a/vcl/source/app/svdata.cxx +++ b/vcl/source/app/svdata.cxx @@ -474,6 +474,13 @@ ImplSVHelpData& ImplGetSVHelpData() } ImplSVData::~ImplSVData() {} + +ImplSVAppData::ImplSVAppData() +{ + m_bUseSystemLoop = getenv("SAL_USE_SYSTEM_LOOP") != nullptr; + SAL_WARN_IF(m_bUseSystemLoop, "vcl.schedule", "Overriding to run LO on system event loop!"); +} + ImplSVAppData::~ImplSVAppData() {} ImplSVGDIData::~ImplSVGDIData() {} ImplSVFrameData::~ImplSVFrameData() {} |