From 684267179e3deb4de8af7a4b8b01948dc6676a79 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 16 Jun 2015 15:24:42 +0200 Subject: [PATCH] Properly delete plugins dependent on failed plugin Init all class member pointers to NULL. This fixes possible crash on exit when dependent plugin was not loaded (e.g. TextEditor was missing). In this case plugin's constructor gets called, initialize() method is _not_ called and destructor gets called -> crash. Properly delete dependent plugins on a plugin which failed to initialize properly. Fix labels of deleted plugins inside an error dialog after pressing "Error Details" from "Installed Plugins" dialog. Change-Id: Iddc029a0f07dcba2501d734d142fb0e69e9383d3 Reviewed-by: Eike Ziller --- src/libs/extensionsystem/pluginmanager.cpp | 14 +++++++--- src/libs/extensionsystem/pluginspec.cpp | 3 --- src/plugins/cpptools/cpptoolsplugin.cpp | 3 ++- src/plugins/cvs/cvsplugin.h | 2 +- src/plugins/debugger/debuggerplugin.cpp | 2 +- src/plugins/fakevim/fakevimplugin.cpp | 27 +++++++++---------- .../projectexplorer/projectexplorer.cpp | 9 +++---- .../qmakeprojectmanagerplugin.cpp | 9 ++----- src/plugins/remotelinux/remotelinuxplugin.cpp | 2 -- src/plugins/subversion/subversionplugin.h | 2 +- 10 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index 82515c24846..441af54b5af 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -1222,8 +1222,12 @@ void PluginManagerPrivate::loadPlugins() while (it.hasPrevious()) { PluginSpec *spec = it.previous(); loadPlugin(spec, PluginSpec::Running); - if (spec->state() == PluginSpec::Running) + if (spec->state() == PluginSpec::Running) { delayedInitializeQueue.append(spec); + } else { + // Plugin initialization failed, so cleanup after it + spec->d->kill(); + } } emit q->pluginsChanged(); @@ -1246,8 +1250,12 @@ void PluginManagerPrivate::shutdown() shutdownEventLoop->exec(); } deleteAll(); - if (!allObjects.isEmpty()) - qDebug() << "There are" << allObjects.size() << "objects left in the plugin manager pool: " << allObjects; + if (!allObjects.isEmpty()) { + qDebug() << "There are" << allObjects.size() << "objects left in the plugin manager pool."; + // Intentionally split debug info here, since in case the list contains + // already deleted object we get at least the info about the number of objects; + qDebug() << "The following objects left in the plugin manager pool:" << allObjects; + } } /*! diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp index f449e484599..efb83fe42f0 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -983,9 +983,6 @@ bool PluginSpecPrivate::initializePlugin() if (!plugin->initialize(arguments, &err)) { errorString = QCoreApplication::translate("PluginSpec", "Plugin initialization failed: %1").arg(err); hasError = true; - // clean up - loader.unload(); - plugin = 0; return false; } state = PluginSpec::Initialized; diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index c125492950f..1719a085f9c 100644 --- a/src/plugins/cpptools/cpptoolsplugin.cpp +++ b/src/plugins/cpptools/cpptoolsplugin.cpp @@ -93,7 +93,6 @@ CppToolsPlugin::CppToolsPlugin() CppToolsPlugin::~CppToolsPlugin() { m_instance = 0; - delete CppModelManager::instance(); } CppToolsPlugin *CppToolsPlugin::instance() @@ -141,6 +140,8 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error) Q_UNUSED(arguments) Q_UNUSED(error) + CppModelManager::instance()->setParent(this); + m_settings = new CppToolsSettings(this); // force registration of cpp tools settings // Objects diff --git a/src/plugins/cvs/cvsplugin.h b/src/plugins/cvs/cvsplugin.h index 47458336725..c06c71bad8e 100644 --- a/src/plugins/cvs/cvsplugin.h +++ b/src/plugins/cvs/cvsplugin.h @@ -167,7 +167,7 @@ private: inline CvsControl *cvsVersionControl() const; CvsSettings m_settings; - CvsClient *m_client; + CvsClient *m_client = nullptr; QString m_commitMessageFileName; QString m_commitRepository; diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 8346359cfc1..74f194b475c 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -3244,7 +3244,6 @@ QSharedPointer globalDebuggerOptions() DebuggerPlugin::DebuggerPlugin() { setObjectName(QLatin1String("DebuggerPlugin")); - addObject(this); dd = new DebuggerPluginPrivate(this); } @@ -3256,6 +3255,7 @@ DebuggerPlugin::~DebuggerPlugin() bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage) { + addObject(this); // Menu groups ActionContainer *mstart = ActionManager::actionContainer(PE::M_DEBUG_STARTDEBUGGING); mstart->appendGroup(Constants::G_GENERAL); diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 52905082cf3..c250d4b13e5 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -1127,7 +1127,7 @@ private: StatusBarWidget *m_statusBar; // @TODO: Delete //WordCompletion *m_wordCompletion; - FakeVimCompletionAssistProvider *m_wordProvider; + FakeVimCompletionAssistProvider *m_wordProvider = nullptr; }; QVariant FakeVimUserCommandsModel::data(const QModelIndex &index, int role) const @@ -1184,6 +1184,18 @@ FakeVimPluginPrivate::FakeVimPluginPrivate(FakeVimPlugin *plugin) } FakeVimPluginPrivate::~FakeVimPluginPrivate() +{ + theFakeVimSettings()->deleteLater(); +} + +void FakeVimPluginPrivate::onCoreAboutToClose() +{ + // Don't attach to editors anymore. + disconnect(EditorManager::instance(), &EditorManager::editorOpened, + this, &FakeVimPluginPrivate::editorOpened); +} + +void FakeVimPluginPrivate::aboutToShutdown() { q->removeObject(m_fakeVimOptionsPage); delete m_fakeVimOptionsPage; @@ -1199,19 +1211,6 @@ FakeVimPluginPrivate::~FakeVimPluginPrivate() delete m_wordProvider; m_wordProvider = 0; - - theFakeVimSettings()->deleteLater(); -} - -void FakeVimPluginPrivate::onCoreAboutToClose() -{ - // Don't attach to editors anymore. - disconnect(EditorManager::instance(), &EditorManager::editorOpened, - this, &FakeVimPluginPrivate::editorOpened); -} - -void FakeVimPluginPrivate::aboutToShutdown() -{ } bool FakeVimPluginPrivate::initialize() diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index c619ca318e8..7f297bbc653 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -356,7 +356,7 @@ public: QString m_projectFilterString; MiniProjectTargetSelector * m_targetSelector; ProjectExplorerSettings m_projectExplorerSettings; - ProjectWelcomePage *m_welcomePage; + ProjectWelcomePage *m_welcomePage = nullptr; IMode *m_projectsMode; TaskHub *m_taskHub; @@ -412,10 +412,6 @@ ProjectExplorerPlugin::~ProjectExplorerPlugin() { JsonWizardFactory::destroyAllFactories(); - removeObject(dd->m_welcomePage); - delete dd->m_welcomePage; - - removeObject(this); // Force sequence of deletion: delete dd->m_kitManager; // remove all the profile information delete dd->m_toolChainManager; @@ -1521,6 +1517,9 @@ ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown() // Attempt to synchronously shutdown all run controls. // If that fails, fall back to asynchronous shutdown (Debugger run controls // might shutdown asynchronously). + removeObject(dd->m_welcomePage); + delete dd->m_welcomePage; + removeObject(this); if (dd->m_outputPane->closeTabs(AppOutputPane::CloseTabNoPrompt /* No prompt any more */)) return SynchronousShutdown; connect(dd->m_outputPane, &AppOutputPane::allRunControlsFinished, diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp index 9500d0d6d9d..8e5789b12f6 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp @@ -77,18 +77,13 @@ using namespace QmakeProjectManager; using namespace ProjectExplorer; QmakeProjectManagerPlugin::QmakeProjectManagerPlugin() - : m_previousStartupProject(0), m_previousTarget(0) + : m_qmakeProjectManager(0), m_previousStartupProject(0), m_previousTarget(0) { } QmakeProjectManagerPlugin::~QmakeProjectManagerPlugin() { - //removeObject(m_embeddedPropertiesPage); - //delete m_embeddedPropertiesPage; - - removeObject(m_qmakeProjectManager); - delete m_qmakeProjectManager; } bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString *errorMessage) @@ -102,7 +97,7 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString //create and register objects m_qmakeProjectManager = new QmakeManager; - addObject(m_qmakeProjectManager); + addAutoReleasedObject(m_qmakeProjectManager); ProjectExplorer::KitManager::registerKitInformation(new QmakeKitInformation); diff --git a/src/plugins/remotelinux/remotelinuxplugin.cpp b/src/plugins/remotelinux/remotelinuxplugin.cpp index 28a4dfcfce2..00c38ac173f 100644 --- a/src/plugins/remotelinux/remotelinuxplugin.cpp +++ b/src/plugins/remotelinux/remotelinuxplugin.cpp @@ -53,7 +53,6 @@ bool RemoteLinuxPlugin::initialize(const QStringList &arguments, Q_UNUSED(arguments) Q_UNUSED(errorMessage) - addObject(this); addAutoReleasedObject(new GenericLinuxDeviceConfigurationFactory); addAutoReleasedObject(new RemoteLinuxRunConfigurationFactory); addAutoReleasedObject(new RemoteLinuxRunControlFactory); @@ -67,7 +66,6 @@ bool RemoteLinuxPlugin::initialize(const QStringList &arguments, RemoteLinuxPlugin::~RemoteLinuxPlugin() { - removeObject(this); } void RemoteLinuxPlugin::extensionsInitialized() diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h index dcc16c3f715..8d7c98eaf10 100644 --- a/src/plugins/subversion/subversionplugin.h +++ b/src/plugins/subversion/subversionplugin.h @@ -149,7 +149,7 @@ private: const QStringList m_svnDirectories; - SubversionClient *m_client; + SubversionClient *m_client = nullptr; QString m_commitMessageFileName; QString m_commitRepository;