From acd51c12b6357aae15bae8450d374b148d125f32 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Thu, 22 Oct 2026 12:50:46 +0200 Subject: [PATCH 1/3] [qt6web] protect teardown process During application shutdown ROOT libraries can be partially unloaded and therefore deletion of timer object registered in the global lists may cause application crash. Same is true for qt6 Url scheme handler. Therefore when gSystem is nullptr - skip objects cleanup --- gui/qt6webdisplay/rootqt6.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/gui/qt6webdisplay/rootqt6.cpp b/gui/qt6webdisplay/rootqt6.cpp index f0caac1eaee10..1497dd5219380 100644 --- a/gui/qt6webdisplay/rootqt6.cpp +++ b/gui/qt6webdisplay/rootqt6.cpp @@ -82,12 +82,16 @@ class RQt6WebDisplayHandle : public RWebDisplayHandle { ~Qt6Creator() override { - /** Code executed during exit and sometime crashes. - * Disable it, while not clear if defaultProfile can be still used - seems to be not */ - // if (fHandler) - // QWebEngineProfile::defaultProfile()->removeUrlSchemeHandler(fHandler.get()); - - R__LOG_DEBUG(0, QtWebDisplayLog()) << "Deleting Qt6Creator"; + /** Code executed during program exit and sometime crashes. + * It can be that ROOT libraries already partially unloaded + * Therefore disable objects cleanup when gSystem already vansihed */ + + if (!gSystem) { + fHandler.release(); + fTimer.release(); + } else if (fHandler && QWebEngineProfile::defaultProfile()) { + QWebEngineProfile::defaultProfile()->removeUrlSchemeHandler(fHandler.get()); + } } std::unique_ptr Display(const RWebDisplayArgs &args) override From 12ec06ef0194f04f5184b77a3e96cdf85e568b50 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Thu, 22 Oct 2026 12:55:06 +0200 Subject: [PATCH 2/3] [qt6web] increase default timer interval From 1 to 10 ms, change name to WebGui.Qt6Timer, was not documented before --- gui/qt6webdisplay/rootqt6.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gui/qt6webdisplay/rootqt6.cpp b/gui/qt6webdisplay/rootqt6.cpp index 1497dd5219380..806bfb899f1b8 100644 --- a/gui/qt6webdisplay/rootqt6.cpp +++ b/gui/qt6webdisplay/rootqt6.cpp @@ -71,10 +71,10 @@ class RQt6WebDisplayHandle : public RWebDisplayHandle { bool fDeleteView = true; ///< is view must be deleted class Qt6Creator : public Creator { - QApplication *qapp{nullptr}; ///< created QApplication - int qargc{1}; ///< arg counter - char *qargv[2]; ///< arg values - std::unique_ptr fTimer; ///< timer to process ROOT events + QApplication *qapp = nullptr; ///< created QApplication + int qargc = 1; ///< arg counter + char *qargv[2] = {nullptr, nullptr}; ///< arg values + std::unique_ptr fTimer; ///< timer to process ROOT events std::unique_ptr fHandler; ///< specialized handler public: @@ -115,7 +115,7 @@ class RQt6WebDisplayHandle : public RWebDisplayHandle { // create timer to process Qt events from inside ROOT process events // very much improve performance, even when Qt even loop runs by QApplication normally if (!fTimer && !args.IsHeadless()) { - Int_t interval = gEnv->GetValue("WebGui.Qt5Timer", 1); + Int_t interval = gEnv->GetValue("WebGui.Qt6Timer", 10); if (interval > 0) { fTimer = std::make_unique(interval, kTRUE); fTimer->TurnOn(); From fbf5bf25845abc66691d34968d40bdd2a680b85e Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Thu, 22 Oct 2026 12:57:29 +0200 Subject: [PATCH 3/3] [webgui] mention Qt6Timer rootrc parameter Was missing in docu --- gui/webdisplay/src/RWebWindowsManager.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gui/webdisplay/src/RWebWindowsManager.cxx b/gui/webdisplay/src/RWebWindowsManager.cxx index d4659fbecd369..d8775364c9a4b 100644 --- a/gui/webdisplay/src/RWebWindowsManager.cxx +++ b/gui/webdisplay/src/RWebWindowsManager.cxx @@ -785,7 +785,8 @@ std::string RWebWindowsManager::GetUrl(RWebWindow &win, bool remote, std::string /// WebGui.LaunchTmout: time required to start process in seconds (default 30 s) /// WebGui.ReconnectTmout: time to reconnect for already existing connection, if negative - no reconnecting possible (default 15 s) /// WebGui.BatchTimeout: time required to produce images in headless (batch) mode (default 30 s) -/// WebGui.CefTimer: periodic time to run CEF event loop (default 10 ms) +/// WebGui.Qt6Timer: periodic timer to run Qt6 event loop, used with 'qt6' web display (default 10 ms) +/// WebGui.CefTimer: periodic timer to run CEF event loop, used with 'cef' web display (default 10 ms) /// WebGui.CefUseViews: "yes" - enable / "no" - disable usage of CEF views frameworks (default is platform/version dependent) /// WebGui.CefLogSeveriry: "disable", "fatal", "error", "warning", "info", "verbose" (default is "fatal") /// WebGui.CefHeadlessTimeout: timeout to wait produce result of headless output (default is 30 s)