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 <eike.ziller@theqtcompany.com>
This commit is contained in:
Jarek Kobus
2015-06-16 15:24:42 +02:00
parent 8131aea4f9
commit 684267179e
10 changed files with 35 additions and 38 deletions

View File

@@ -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;
}
}
/*!

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -3244,7 +3244,6 @@ QSharedPointer<Internal::GlobalDebuggerOptions> 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);

View File

@@ -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()

View File

@@ -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,

View File

@@ -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);

View File

@@ -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()

View File

@@ -149,7 +149,7 @@ private:
const QStringList m_svnDirectories;
SubversionClient *m_client;
SubversionClient *m_client = nullptr;
QString m_commitMessageFileName;
QString m_commitRepository;