From 2d2d136952b748773e72c3d350b83269ddbd996f Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Wed, 25 Sep 2024 12:29:05 +0200 Subject: [PATCH] Lua: Make OptionsPage safer If the calling script does not keep a reference to the OptionsPage it will be garbage collected by Lua eventually. That can happen while the SettingsDialog is open, which cannot cope with a page being destroyed while its open. For now we just keep the OptionsPage alive until the plugin is unloaded. Change-Id: I8d0592731236482bbdc35078c24a5c6b962b1147 Reviewed-by: hjk --- src/plugins/lua/bindings/settings.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/plugins/lua/bindings/settings.cpp b/src/plugins/lua/bindings/settings.cpp index 0474fa50552..64ecd1e8dc0 100644 --- a/src/plugins/lua/bindings/settings.cpp +++ b/src/plugins/lua/bindings/settings.cpp @@ -286,9 +286,23 @@ sol::usertype addTypedAspect(sol::table &lua, const QString &name) sol::bases, BaseAspect>()); } +class ObjectPool +{ +public: + mutable std::vector> optionsPages; + + template + std::shared_ptr makePage(_Args &&...__args) const + { + auto page = std::make_shared(std::forward<_Args>(__args)...); + optionsPages.push_back(page); + return page; + } +}; + void setupSettingsModule() { - registerProvider("Settings", [](sol::state_view lua) -> sol::object { + registerProvider("Settings", [pool = ObjectPool()](sol::state_view lua) -> sol::object { const ScriptPluginSpec *pluginSpec = lua.get("PluginSpec"); sol::table settings = lua.create_table(); @@ -607,8 +621,8 @@ void setupSettingsModule() settings.new_usertype( "OptionsPage", "create", - [pluginSpec](const sol::table &options) { - return std::make_unique(pluginSpec, options); + [&pool, pluginSpec](const sol::table &options) { + return pool.makePage(pluginSpec, options); }, "show", [](OptionsPage *page) { Core::ICore::showOptionsDialog(page->id()); }); @@ -616,8 +630,8 @@ void setupSettingsModule() settings.new_usertype( "ExtensionOptionsPage", "create", - [pluginSpec](AspectContainer *container) { - return std::make_unique(pluginSpec, container); + [pluginSpec, &pool](AspectContainer *container) { + return pool.makePage(pluginSpec, container); }, "show", [](ExtensionOptionsPage *page) { Core::ICore::showOptionsDialog(page->id()); });