From 23d78663deb5fcca0a62aba6c1e3be2392a23efa Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 10 Mar 2021 12:25:39 +0100 Subject: [PATCH 1/3] manage ownership of plugin loaders --- src/common/plugins/plugin_manager.cpp | 26 ++++++++++++++++++-------- src/common/plugins/plugin_manager.h | 6 +++--- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/common/plugins/plugin_manager.cpp b/src/common/plugins/plugin_manager.cpp index bfba5af8f..697c9890a 100644 --- a/src/common/plugins/plugin_manager.cpp +++ b/src/common/plugins/plugin_manager.cpp @@ -22,13 +22,14 @@ ****************************************************************************/ #include "plugin_manager.h" -#include "meshlab_plugin_type.h" + #include -#include -#include -#include +#include +#include + #include +#include "meshlab_plugin_type.h" #include "../mlexception.h" #include "../globals.h" @@ -53,8 +54,10 @@ PluginManager::PluginManager() PluginManager::~PluginManager() { - for (auto& plugin : allPlugins) + for (auto& plugin : allPluginLoaders){ + plugin->unload(); delete plugin; + } } /** @@ -121,6 +124,8 @@ void PluginManager::checkPlugin(const QString& filename) if (type.isFilterPlugin()){ checkFilterPlugin(qobject_cast(plugin)); } + + loader.unload(); } /** @@ -188,8 +193,8 @@ void PluginManager::loadPlugin(const QString& fileName) checkPlugin(fileName); //load the plugin depending on the type (can be more than one type!) - QPluginLoader loader(fin.absoluteFilePath()); - QObject *plugin = loader.instance(); + QPluginLoader* loader = new QPluginLoader(fin.absoluteFilePath()); + QObject *plugin = loader->instance(); MeshLabPluginFile* ifp = dynamic_cast(plugin); MeshLabPluginType type(ifp); @@ -216,6 +221,7 @@ void PluginManager::loadPlugin(const QString& fileName) //of all plugins ifp->plugFileInfo = fin; allPlugins.push_back(ifp); + allPluginLoaders.push_back(loader); pluginFiles.insert(fin.absoluteFilePath()); } @@ -223,6 +229,7 @@ void PluginManager::unloadPlugin(MeshLabPluginFile* ifp) { auto it = std::find(allPlugins.begin(), allPlugins.end(), ifp); if (it != allPlugins.end()){ + unsigned int index = it - allPlugins.begin(); MeshLabPluginType type(ifp); if (type.isDecoratePlugin()){ decoratePlugins.eraseDecoratePlugin(dynamic_cast(ifp)); @@ -242,8 +249,11 @@ void PluginManager::unloadPlugin(MeshLabPluginFile* ifp) if (type.isRenderPlugin()){ renderPlugins.eraseRenderPlugin(dynamic_cast(ifp)); } + QPluginLoader* l = allPluginLoaders[index]; + allPluginLoaders.erase(allPluginLoaders.begin() + index); allPlugins.erase(it); - delete ifp; + l->unload(); + delete l; } } diff --git a/src/common/plugins/plugin_manager.h b/src/common/plugins/plugin_manager.h index ffa007b06..b7a160bdd 100644 --- a/src/common/plugins/plugin_manager.h +++ b/src/common/plugins/plugin_manager.h @@ -31,9 +31,8 @@ #include "containers/ioraster_plugin_container.h" #include "containers/render_plugin_container.h" -#include -#include -#include +#include +#include /** * @brief The PluginManager class provides the basic tools for managing all the plugins. @@ -91,6 +90,7 @@ public: private: //all plugins std::vector allPlugins; + std::vector allPluginLoaders; std::set pluginFiles; //used to check if a plugin file has been already loaded //Plugin containers: used for better organization of each type of plugin From 19a8919e129c5ffa76716fb621f3dfc50c7e6dbc Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 10 Mar 2021 13:03:21 +0100 Subject: [PATCH 2/3] temporary warning message when impossible to delete dll --- src/meshlab/dialogs/plugin_info_dialog.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/meshlab/dialogs/plugin_info_dialog.cpp b/src/meshlab/dialogs/plugin_info_dialog.cpp index 8d865ce59..221ce5cc5 100644 --- a/src/meshlab/dialogs/plugin_info_dialog.cpp +++ b/src/meshlab/dialogs/plugin_info_dialog.cpp @@ -89,7 +89,14 @@ void PluginInfoDialog::uninstallPluginPushButtonClicked() MeshLabPluginFile* fpi = pm[nPlug]; QFileInfo fdel = fpi->pluginFileInfo(); pm.unloadPlugin(fpi); - QFile::remove(fdel.absoluteFilePath()); + bool res = QFile::remove(fdel.absoluteFilePath()); + if (!res){ + //pm.loadPlugin(fdel.absoluteFilePath()); + QMessageBox::warning( + this, "Error while deleting plugin.", + "Impossible to delete the plugin. Please delete manually the following file (or disable the plugin):\n" + + fdel.absoluteFilePath()); + } ui->treeWidget->clear(); populateTreeWidget(); ui->treeWidget->update(); From cd36d7db8808a358aa8d2ba20b2b9ff9d80b3968 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 10 Mar 2021 13:23:27 +0100 Subject: [PATCH 3/3] set a plugin to be deleted when starting next session --- src/meshlab/dialogs/plugin_info_dialog.cpp | 13 +++++++++---- src/meshlab/mainwindow_Init.cpp | 17 +++++++++++++++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/meshlab/dialogs/plugin_info_dialog.cpp b/src/meshlab/dialogs/plugin_info_dialog.cpp index 221ce5cc5..b0fb15351 100644 --- a/src/meshlab/dialogs/plugin_info_dialog.cpp +++ b/src/meshlab/dialogs/plugin_info_dialog.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -91,11 +92,15 @@ void PluginInfoDialog::uninstallPluginPushButtonClicked() pm.unloadPlugin(fpi); bool res = QFile::remove(fdel.absoluteFilePath()); if (!res){ + QSettings settings; + QStringList toDeletePlugins = settings.value("ToDeletePlugins").value(); + toDeletePlugins.append(fdel.absoluteFilePath()); + settings.setValue("ToDeletePlugins", toDeletePlugins); //pm.loadPlugin(fdel.absoluteFilePath()); - QMessageBox::warning( - this, "Error while deleting plugin.", - "Impossible to delete the plugin. Please delete manually the following file (or disable the plugin):\n" - + fdel.absoluteFilePath()); + //QMessageBox::warning( + // this, "Error while deleting plugin.", + // "Impossible to delete the plugin. Please delete manually the following file (or disable the plugin):\n" + // + fdel.absoluteFilePath()); } ui->treeWidget->clear(); populateTreeWidget(); diff --git a/src/meshlab/mainwindow_Init.cpp b/src/meshlab/mainwindow_Init.cpp index f30551bc5..db583c28d 100644 --- a/src/meshlab/mainwindow_Init.cpp +++ b/src/meshlab/mainwindow_Init.cpp @@ -54,6 +54,21 @@ MainWindow::MainWindow(): PM(meshlab::pluginManagerInstance()), _currviewcontainer(NULL) { + QSettings settings; + //toDelete plugins, flagged in the last session + //this is needed on windows, since it refuses to delete dll plugins while meshlab is + //running. Therefore, in these cases plugins that are going to be deleted are + //saved in this list, and the files are removed in the next meshlab session, + //BEFORE they will be loaded. Therefore, these lines need to be executed + //before the PM.loadPlugins call. + QStringList toDeletePlugins = settings.value("ToDeletePlugins").value(); + if (!toDeletePlugins.isEmpty()){ + for (const QString& file : toDeletePlugins){ + QFile::remove(file); + } + } + settings.remove("ToDeletePlugins"); + setContextMenuPolicy(Qt::NoContextMenu); //workspace = new QWorkspace(this); @@ -70,7 +85,6 @@ MainWindow::MainWindow(): catch (const MLException& e) { QMessageBox::warning(this, "Error while loading plugins.", e.what()); } - QSettings settings; //disable previously disabled plugins QStringList disabledPlugins = settings.value("DisabledPlugins").value(); @@ -78,7 +92,6 @@ MainWindow::MainWindow(): if (disabledPlugins.contains(fp->pluginName())) PM.disablePlugin(fp); } - //setCentralWidget(workspace); setCentralWidget(mdiarea);