summaryrefslogtreecommitdiff
path: root/src/plugins/coreplugin
diff options
context:
space:
mode:
authorTobias Hunger <tobias.hunger@qt.io>2016-10-17 12:17:51 +0200
committerTobias Hunger <tobias.hunger@qt.io>2016-10-28 12:28:46 +0000
commitb75c6444d1d0f3abb796b23d78a24029f9fb5093 (patch)
tree504e4c6c90b2ca26cc22a58346f0a41f03196982 /src/plugins/coreplugin
parent9e72dc343c5b100b35a4c52ca9f34e6989156244 (diff)
downloadqt-creator-b75c6444d1d0f3abb796b23d78a24029f9fb5093.tar.gz
Core: Add a reaper that will asynchronously clean up QProcesses
Change-Id: Ic24dde261eac775d1a5854b8dbcbfeb002d0f729 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Diffstat (limited to 'src/plugins/coreplugin')
-rw-r--r--src/plugins/coreplugin/coreplugin.cpp1
-rw-r--r--src/plugins/coreplugin/coreplugin.h3
-rw-r--r--src/plugins/coreplugin/coreplugin.pro3
-rw-r--r--src/plugins/coreplugin/coreplugin.qbs1
-rw-r--r--src/plugins/coreplugin/reaper.cpp114
-rw-r--r--src/plugins/coreplugin/reaper.h38
-rw-r--r--src/plugins/coreplugin/reaper_p.h71
7 files changed, 231 insertions, 0 deletions
diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp
index 75df422801..2dcdad00e3 100644
--- a/src/plugins/coreplugin/coreplugin.cpp
+++ b/src/plugins/coreplugin/coreplugin.cpp
@@ -32,6 +32,7 @@
#include "modemanager.h"
#include "infobar.h"
#include "iwizardfactory.h"
+#include "reaper_p.h"
#include "themechooser.h"
#include <coreplugin/actionmanager/actionmanager.h>
diff --git a/src/plugins/coreplugin/coreplugin.h b/src/plugins/coreplugin/coreplugin.h
index c6135ed85c..d86daa21d1 100644
--- a/src/plugins/coreplugin/coreplugin.h
+++ b/src/plugins/coreplugin/coreplugin.h
@@ -25,6 +25,8 @@
#pragma once
+#include "reaper_p.h"
+
#include <extensionsystem/iplugin.h>
QT_BEGIN_NAMESPACE
@@ -85,6 +87,7 @@ private:
EditMode *m_editMode;
DesignMode *m_designMode;
Locator *m_locator;
+ ReaperPrivate m_reaper;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro
index 6de7837acf..035316e5d0 100644
--- a/src/plugins/coreplugin/coreplugin.pro
+++ b/src/plugins/coreplugin/coreplugin.pro
@@ -56,6 +56,7 @@ SOURCES += corejsextensions.cpp \
progressmanager/progressview.cpp \
progressmanager/progressbar.cpp \
progressmanager/futureprogress.cpp \
+ reaper.cpp \
statusbarwidget.cpp \
coreplugin.cpp \
modemanager.cpp \
@@ -160,6 +161,8 @@ HEADERS += corejsextensions.h \
progressmanager/progressbar.h \
progressmanager/futureprogress.h \
progressmanager/progressmanager.h \
+ reaper.h \
+ reaper_p.h \
icontext.h \
icore.h \
infobar.h \
diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs
index fe6b3cb75e..e6ea7f8d3c 100644
--- a/src/plugins/coreplugin/coreplugin.qbs
+++ b/src/plugins/coreplugin/coreplugin.qbs
@@ -88,6 +88,7 @@ Project {
"outputwindow.cpp", "outputwindow.h",
"patchtool.cpp", "patchtool.h",
"plugindialog.cpp", "plugindialog.h",
+ "reaper.cpp", "reaper.h", "reaper_p.h",
"removefiledialog.cpp", "removefiledialog.h", "removefiledialog.ui",
"rightpane.cpp", "rightpane.h",
"settingsdatabase.cpp", "settingsdatabase.h",
diff --git a/src/plugins/coreplugin/reaper.cpp b/src/plugins/coreplugin/reaper.cpp
new file mode 100644
index 0000000000..fabdcdb26c
--- /dev/null
+++ b/src/plugins/coreplugin/reaper.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "reaper.h"
+#include "reaper_p.h"
+
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+
+namespace Core {
+namespace Internal {
+
+static ReaperPrivate *d = nullptr;
+
+ProcessReaper::ProcessReaper(QProcess *p, int timeoutMs) : m_process(p)
+{
+ m_iterationTimer.setInterval(timeoutMs);
+ m_iterationTimer.setSingleShot(true);
+ connect(&m_iterationTimer, &QTimer::timeout, this, &ProcessReaper::nextIteration);
+
+ QTimer::singleShot(0, this, &ProcessReaper::nextIteration);
+ m_futureInterface.reportStarted();
+}
+
+void ProcessReaper::nextIteration()
+{
+ QProcess::ProcessState state = m_process->state();
+ if (state == QProcess::NotRunning || m_emergencyCounter > 5) {
+ delete m_process;
+ m_futureInterface.reportFinished();
+ return;
+ }
+
+ if (state == QProcess::Starting) {
+ if (m_lastState == QProcess::Starting)
+ m_process->kill();
+ } else if (state == QProcess::Running) {
+ if (m_lastState == QProcess::Running)
+ m_process->kill();
+ else
+ m_process->terminate();
+ }
+
+ m_lastState = state;
+ m_iterationTimer.start();
+
+ ++m_emergencyCounter;
+}
+
+ReaperPrivate::ReaperPrivate()
+{
+ d = this;
+}
+
+ReaperPrivate::~ReaperPrivate()
+{
+ d = nullptr;
+}
+
+} // namespace Internal
+
+namespace Reaper {
+
+void reap(QProcess *process, int timeoutMs)
+{
+ if (!process)
+ return;
+
+ QTC_ASSERT(Internal::d, return);
+
+ auto reaper = new Internal::ProcessReaper(process, timeoutMs);
+ QFuture<void> f = reaper->future();
+
+ Internal::d->m_synchronizer.addFuture(f);
+ auto watcher = new QFutureWatcher<void>();
+ watcher->setFuture(f);
+
+ QObject::connect(watcher, &QFutureWatcher<void>::finished, [watcher, reaper]() {
+ watcher->deleteLater();
+
+ const QList<QFuture<void>> futures = Utils::filtered(Internal::d->m_synchronizer.futures(),
+ [reaper](const QFuture<void> &f) { return reaper->future() != f; });
+ for (const QFuture<void> &f : futures)
+ Internal::d->m_synchronizer.addFuture(f);
+
+ delete reaper;
+ });
+}
+
+} // namespace Reaper
+} // namespace Core
+
diff --git a/src/plugins/coreplugin/reaper.h b/src/plugins/coreplugin/reaper.h
new file mode 100644
index 0000000000..7c2b2a356a
--- /dev/null
+++ b/src/plugins/coreplugin/reaper.h
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "core_global.h"
+
+QT_FORWARD_DECLARE_CLASS(QProcess);
+
+namespace Core {
+namespace Reaper {
+
+CORE_EXPORT void reap(QProcess *p, int timeoutMs = 500);
+
+} // namespace Reaper
+} // namespace Core
diff --git a/src/plugins/coreplugin/reaper_p.h b/src/plugins/coreplugin/reaper_p.h
new file mode 100644
index 0000000000..e0995f027e
--- /dev/null
+++ b/src/plugins/coreplugin/reaper_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+#include <QFutureSynchronizer>
+#include <QFutureWatcher>
+#include <QProcess>
+#include <QTimer>
+
+namespace Core {
+namespace Internal {
+
+class CorePlugin;
+
+class ProcessReaper : public QObject
+{
+ Q_OBJECT
+
+public:
+ ProcessReaper(QProcess *p, int timeoutMs);
+
+ QFuture<void> future() { return m_futureInterface.future(); }
+
+private:
+ void nextIteration();
+
+ QTimer m_iterationTimer;
+ QFutureInterface<void> m_futureInterface;
+ QProcess *m_process;
+ int m_emergencyCounter = 0;
+ QProcess::ProcessState m_lastState = QProcess::NotRunning;
+};
+
+class ReaperPrivate {
+public:
+ ~ReaperPrivate();
+
+ QFutureSynchronizer<void> m_synchronizer;
+
+private:
+ ReaperPrivate();
+
+ friend class CorePlugin;
+};
+
+} // namespace Internal
+} // namespace Core