aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhjk <hjk@qt.io>2021-05-05 18:21:22 +0200
committerhjk <hjk@qt.io>2021-05-10 09:47:51 +0000
commitc23cdd926262a977a987cd887be8f4fd02386d92 (patch)
tree4b0a6dad23ed35fb4ce2fcb8d87f6254681a1629
parent040d0cc1ef877a72b20717b193efa2104240db2b (diff)
Utils: Merge {synchronous,qtc}process.{h,cpp} file pairs
Mechanical to prepare merging the actual classes. Adapting #includes. Change-Id: I77a2c28129287778bc870c30cb890cd26bc2e62b Reviewed-by: Christian Stenger <christian.stenger@qt.io>
-rw-r--r--src/libs/extensionsystem/pluginmanager.cpp2
-rw-r--r--src/libs/utils/CMakeLists.txt1
-rw-r--r--src/libs/utils/buildablehelperlibrary.cpp1
-rw-r--r--src/libs/utils/pathchooser.cpp7
-rw-r--r--src/libs/utils/qtcprocess.cpp588
-rw-r--r--src/libs/utils/qtcprocess.h113
-rw-r--r--src/libs/utils/shellcommand.h6
-rw-r--r--src/libs/utils/synchronousprocess.cpp591
-rw-r--r--src/libs/utils/synchronousprocess.h144
-rw-r--r--src/libs/utils/utils-lib.pri2
-rw-r--r--src/libs/utils/utils.qbs2
-rw-r--r--src/plugins/android/androidavdmanager.cpp5
-rw-r--r--src/plugins/android/androidbuildapkstep.cpp1
-rw-r--r--src/plugins/android/androidconfigurations.cpp2
-rw-r--r--src/plugins/android/androidcreatekeystorecertificate.cpp2
-rw-r--r--src/plugins/android/androiddeployqtstep.cpp1
-rw-r--r--src/plugins/android/androidmanager.cpp2
-rw-r--r--src/plugins/android/androidrunnerworker.cpp1
-rw-r--r--src/plugins/android/androidsdkmanager.cpp1
-rw-r--r--src/plugins/android/androidsettingswidget.cpp1
-rw-r--r--src/plugins/baremetal/iarewtoolchain.cpp1
-rw-r--r--src/plugins/baremetal/keiltoolchain.cpp1
-rw-r--r--src/plugins/baremetal/sdcctoolchain.cpp2
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp2
-rw-r--r--src/plugins/beautifier/beautifierplugin.cpp2
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifysettings.cpp2
-rw-r--r--src/plugins/clangtools/clangtidyclazyrunner.cpp2
-rw-r--r--src/plugins/clangtools/clangtoolrunner.cpp2
-rw-r--r--src/plugins/clangtools/clangtoolsutils.cpp3
-rw-r--r--src/plugins/clangtools/executableinfo.cpp2
-rw-r--r--src/plugins/clearcase/clearcaseplugin.cpp2
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketool.h2
-rw-r--r--src/plugins/coreplugin/plugininstallwizard.cpp2
-rw-r--r--src/plugins/cvs/cvsplugin.cpp2
-rw-r--r--src/plugins/debugger/debuggeritem.cpp2
-rw-r--r--src/plugins/debugger/debuggeritemmanager.cpp2
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp1
-rw-r--r--src/plugins/git/gerrit/gerritserver.cpp3
-rw-r--r--src/plugins/git/gitclient.cpp1
-rw-r--r--src/plugins/git/gitgrep.cpp2
-rw-r--r--src/plugins/ios/iosconfigurations.cpp11
-rw-r--r--src/plugins/ios/iosprobe.cpp2
-rw-r--r--src/plugins/ios/iostoolhandler.cpp8
-rw-r--r--src/plugins/ios/simulatorcontrol.cpp2
-rw-r--r--src/plugins/languageclient/client.cpp8
-rw-r--r--src/plugins/mercurial/mercurialclient.cpp3
-rw-r--r--src/plugins/perforce/perforceplugin.cpp4
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp2
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.cpp2
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.cpp1
-rw-r--r--src/plugins/python/pythonsettings.cpp4
-rw-r--r--src/plugins/python/pythonutils.cpp1
-rw-r--r--src/plugins/subversion/subversionclient.cpp8
-rw-r--r--src/plugins/subversion/subversionplugin.cpp2
-rw-r--r--src/plugins/texteditor/formattexteditor.cpp4
-rw-r--r--src/plugins/texteditor/highlightersettings.cpp2
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.cpp2
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.h2
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.cpp2
-rw-r--r--tests/auto/debugger/tst_dumpers.cpp6
-rw-r--r--tests/manual/process/mainwindow.cpp2
61 files changed, 767 insertions, 822 deletions
diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp
index ab83ed210b..8de3319f85 100644
--- a/src/libs/extensionsystem/pluginmanager.cpp
+++ b/src/libs/extensionsystem/pluginmanager.cpp
@@ -55,8 +55,8 @@
#include <utils/hostosinfo.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/qtcsettings.h>
-#include <utils/synchronousprocess.h>
#ifdef WITH_TESTS
#include <utils/hostosinfo.h>
diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt
index de4d340ad6..c499eaab40 100644
--- a/src/libs/utils/CMakeLists.txt
+++ b/src/libs/utils/CMakeLists.txt
@@ -151,7 +151,6 @@ add_qtc_library(Utils
stringutils.cpp stringutils.h
styledbar.cpp styledbar.h
stylehelper.cpp stylehelper.h
- synchronousprocess.cpp synchronousprocess.h
templateengine.cpp templateengine.h
temporarydirectory.cpp temporarydirectory.h
temporaryfile.cpp temporaryfile.h
diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp
index 835c876bc5..dba4ade975 100644
--- a/src/libs/utils/buildablehelperlibrary.cpp
+++ b/src/libs/utils/buildablehelperlibrary.cpp
@@ -25,7 +25,6 @@
#include "buildablehelperlibrary.h"
#include "hostosinfo.h"
-#include "synchronousprocess.h"
#include "qtcprocess.h"
#include <QDateTime>
diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp
index 3ee14ab466..ec3fe910ae 100644
--- a/src/libs/utils/pathchooser.cpp
+++ b/src/libs/utils/pathchooser.cpp
@@ -26,11 +26,10 @@
#include "pathchooser.h"
#include "environment.h"
-#include "qtcassert.h"
-#include "macroexpander.h"
-
-#include "synchronousprocess.h"
#include "hostosinfo.h"
+#include "macroexpander.h"
+#include "qtcassert.h"
+#include "qtcprocess.h"
#include "theme/theme.h"
#include <QDebug>
diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp
index 51fb60f4ae..e8af30c7a5 100644
--- a/src/libs/utils/qtcprocess.cpp
+++ b/src/libs/utils/qtcprocess.cpp
@@ -24,17 +24,22 @@
****************************************************************************/
#include "qtcprocess.h"
-#include "stringutils.h"
-#include <utils/qtcassert.h>
-#include <utils/hostosinfo.h>
+#include "stringutils.h"
+#include "executeondestruction.h"
+#include "hostosinfo.h"
+#include "qtcassert.h"
+#include "qtcprocess.h"
#include <QCoreApplication>
-#include <QDir>
#include <QDebug>
+#include <QDir>
+#include <QLoggingCategory>
#include <QRegularExpression>
#include <QStack>
+#include <QTextCodec>
#include <QThread>
+#include <QTimer>
#ifdef QT_GUI_LIB
// qmlpuppet does not use that.
@@ -42,6 +47,10 @@
#include <QMessageBox>
#endif
+#include <algorithm>
+#include <limits.h>
+#include <memory>
+
#ifdef Q_OS_WIN
#define CALLBACK WINAPI
#include <qt_windows.h>
@@ -1845,4 +1854,575 @@ QString QtcProcess::locateBinary(const QString &binary)
return locateBinary(QString::fromLocal8Bit(path), binary);
}
+
+/*!
+ \class Utils::SynchronousProcess
+
+ \brief The SynchronousProcess class runs a synchronous process in its own
+ event loop that blocks only user input events. Thus, it allows for the GUI to
+ repaint and append output to log windows.
+
+ The stdOut(), stdErr() signals are emitted unbuffered as the process
+ writes them.
+
+ The stdOutBuffered(), stdErrBuffered() signals are emitted with complete
+ lines based on the '\\n' marker if they are enabled using
+ stdOutBufferedSignalsEnabled()/setStdErrBufferedSignalsEnabled().
+ They would typically be used for log windows.
+
+ There is a timeout handling that takes effect after the last data have been
+ read from stdout/stdin (as opposed to waitForFinished(), which measures time
+ since it was invoked). It is thus also suitable for slow processes that
+ continuously output data (like version system operations).
+
+ The property timeOutMessageBoxEnabled influences whether a message box is
+ shown asking the user if they want to kill the process on timeout (default: false).
+
+ There are also static utility functions for dealing with fully synchronous
+ processes, like reading the output with correct timeout handling.
+
+ Caution: This class should NOT be used if there is a chance that the process
+ triggers opening dialog boxes (for example, by file watchers triggering),
+ as this will cause event loop problems.
+*/
+
+enum { debug = 0 };
+enum { syncDebug = 0 };
+
+enum { defaultMaxHangTimerCount = 10 };
+
+static Q_LOGGING_CATEGORY(processLog, "qtc.utils.synchronousprocess", QtWarningMsg);
+
+// ----------- SynchronousProcessResponse
+void SynchronousProcessResponse::clear()
+{
+ result = StartFailed;
+ exitCode = -1;
+ rawStdOut.clear();
+ rawStdErr.clear();
+}
+
+QString SynchronousProcessResponse::exitMessage(const QString &binary, int timeoutS) const
+{
+ switch (result) {
+ case Finished:
+ return SynchronousProcess::tr("The command \"%1\" finished successfully.").arg(QDir::toNativeSeparators(binary));
+ case FinishedError:
+ return SynchronousProcess::tr("The command \"%1\" terminated with exit code %2.").arg(QDir::toNativeSeparators(binary)).arg(exitCode);
+ case TerminatedAbnormally:
+ return SynchronousProcess::tr("The command \"%1\" terminated abnormally.").arg(QDir::toNativeSeparators(binary));
+ case StartFailed:
+ return SynchronousProcess::tr("The command \"%1\" could not be started.").arg(QDir::toNativeSeparators(binary));
+ case Hang:
+ return SynchronousProcess::tr("The command \"%1\" did not respond within the timeout limit (%2 s).")
+ .arg(QDir::toNativeSeparators(binary)).arg(timeoutS);
+ }
+ return QString();
+}
+
+QByteArray SynchronousProcessResponse::allRawOutput() const
+{
+ if (!rawStdOut.isEmpty() && !rawStdErr.isEmpty()) {
+ QByteArray result = rawStdOut;
+ if (!result.endsWith('\n'))
+ result += '\n';
+ result += rawStdErr;
+ return result;
+ }
+ return !rawStdOut.isEmpty() ? rawStdOut : rawStdErr;
+}
+
+QString SynchronousProcessResponse::allOutput() const
+{
+ const QString out = stdOut();
+ const QString err = stdErr();
+
+ if (!out.isEmpty() && !err.isEmpty()) {
+ QString result = out;
+ if (!result.endsWith('\n'))
+ result += '\n';
+ result += err;
+ return result;
+ }
+ return !out.isEmpty() ? out : err;
+}
+
+QString SynchronousProcessResponse::stdOut() const
+{
+ return QtcProcess::normalizeNewlines(codec->toUnicode(rawStdOut));
+}
+
+QString SynchronousProcessResponse::stdErr() const
+{
+ return QtcProcess::normalizeNewlines(codec->toUnicode(rawStdErr));
+}
+
+QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse& r)
+{
+ QDebug nsp = str.nospace();
+ nsp << "SynchronousProcessResponse: result=" << r.result << " ex=" << r.exitCode << '\n'
+ << r.rawStdOut.size() << " bytes stdout, stderr=" << r.rawStdErr << '\n';
+ return str;
+}
+
+SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code)
+{
+ return code ? SynchronousProcessResponse::FinishedError
+ : SynchronousProcessResponse::Finished;
+}
+
+// Data for one channel buffer (stderr/stdout)
+class ChannelBuffer : public QObject
+{
+ Q_OBJECT
+
+public:
+ void clearForRun();
+
+ QString linesRead();
+ void append(const QByteArray &text, bool emitSignals);
+
+ QByteArray rawData;
+ QString incompleteLineBuffer; // lines not yet signaled
+ QTextCodec *codec = nullptr; // Not owner
+ std::unique_ptr<QTextCodec::ConverterState> codecState;
+ int rawDataPos = 0;
+ bool bufferedSignalsEnabled = false;
+ bool firstBuffer = true;
+
+signals:
+ void outputBuffered(const QString &text, bool firstTime);
+};
+
+void ChannelBuffer::clearForRun()
+{
+ firstBuffer = true;
+ rawDataPos = 0;
+ rawData.clear();
+ codecState.reset(new QTextCodec::ConverterState);
+ incompleteLineBuffer.clear();
+}
+
+/* Check for complete lines read from the device and return them, moving the
+ * buffer position. */
+QString ChannelBuffer::linesRead()
+{
+ // Convert and append the new input to the buffer of incomplete lines
+ const char *start = rawData.constData() + rawDataPos;
+ const int len = rawData.size() - rawDataPos;
+ incompleteLineBuffer.append(codec->toUnicode(start, len, codecState.get()));
+ rawDataPos = rawData.size();
+
+ // Any completed lines in the incompleteLineBuffer?
+ const int lastLineIndex = qMax(incompleteLineBuffer.lastIndexOf('\n'),
+ incompleteLineBuffer.lastIndexOf('\r'));
+ if (lastLineIndex == -1)
+ return QString();
+
+ // Get completed lines and remove them from the incompleteLinesBuffer:
+ const QString lines = QtcProcess::normalizeNewlines(incompleteLineBuffer.left(lastLineIndex + 1));
+ incompleteLineBuffer = incompleteLineBuffer.mid(lastLineIndex + 1);
+
+ return lines;
+}
+
+void ChannelBuffer::append(const QByteArray &text, bool emitSignals)
+{
+ if (text.isEmpty())
+ return;
+ rawData += text;
+ if (!emitSignals)
+ return;
+
+ // Buffered. Emit complete lines?
+ if (bufferedSignalsEnabled) {
+ const QString lines = linesRead();
+ if (!lines.isEmpty()) {
+ emit outputBuffered(lines, firstBuffer);
+ firstBuffer = false;
+ }
+ }
+}
+
+// ----------- SynchronousProcessPrivate
+class SynchronousProcessPrivate {
+public:
+ void clearForRun();
+
+ QTextCodec *m_codec = QTextCodec::codecForLocale();
+ QtcProcess m_process;
+ QTimer m_timer;
+ QEventLoop m_eventLoop;
+ SynchronousProcessResponse m_result;
+ FilePath m_binary;
+ ChannelBuffer m_stdOut;
+ ChannelBuffer m_stdErr;
+ ExitCodeInterpreter m_exitCodeInterpreter = defaultExitCodeInterpreter;
+
+ int m_hangTimerCount = 0;
+ int m_maxHangTimerCount = defaultMaxHangTimerCount;
+ bool m_startFailure = false;
+ bool m_timeOutMessageBoxEnabled = false;
+ bool m_waitingForUser = false;
+};
+
+void SynchronousProcessPrivate::clearForRun()
+{
+ m_hangTimerCount = 0;
+ m_stdOut.clearForRun();
+ m_stdOut.codec = m_codec;
+ m_stdErr.clearForRun();
+ m_stdErr.codec = m_codec;
+ m_result.clear();
+ m_result.codec = m_codec;
+ m_startFailure = false;
+ m_binary = {};
+}
+
+// ----------- SynchronousProcess
+SynchronousProcess::SynchronousProcess() :
+ d(new SynchronousProcessPrivate)
+{
+ d->m_timer.setInterval(1000);
+ connect(&d->m_timer, &QTimer::timeout, this, &SynchronousProcess::slotTimeout);
+ connect(&d->m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+ this, &SynchronousProcess::finished);
+ connect(&d->m_process, &QProcess::errorOccurred, this, &SynchronousProcess::error);
+ connect(&d->m_process, &QProcess::readyReadStandardOutput,
+ this, [this]() {
+ d->m_hangTimerCount = 0;
+ processStdOut(true);
+ });
+ connect(&d->m_process, &QProcess::readyReadStandardError,
+ this, [this]() {
+ d->m_hangTimerCount = 0;
+ processStdErr(true);
+ });
+ connect(&d->m_stdOut, &ChannelBuffer::outputBuffered, this, &SynchronousProcess::stdOutBuffered);
+ connect(&d->m_stdErr, &ChannelBuffer::outputBuffered, this, &SynchronousProcess::stdErrBuffered);
+}
+
+SynchronousProcess::~SynchronousProcess()
+{
+ disconnect(&d->m_timer, nullptr, this, nullptr);
+ disconnect(&d->m_process, nullptr, this, nullptr);
+ delete d;
+}
+
+void SynchronousProcess::setTimeoutS(int timeoutS)
+{
+ if (timeoutS > 0)
+ d->m_maxHangTimerCount = qMax(2, timeoutS);
+ else
+ d->m_maxHangTimerCount = INT_MAX / 1000;
+}
+
+int SynchronousProcess::timeoutS() const
+{
+ return d->m_maxHangTimerCount == (INT_MAX / 1000) ? -1 : d->m_maxHangTimerCount;
+}
+
+void SynchronousProcess::setCodec(QTextCodec *c)
+{
+ QTC_ASSERT(c, return);
+ d->m_codec = c;
+}
+
+QTextCodec *SynchronousProcess::codec() const
+{
+ return d->m_codec;
+}
+
+bool SynchronousProcess::stdOutBufferedSignalsEnabled() const
+{
+ return d->m_stdOut.bufferedSignalsEnabled;
+}
+
+void SynchronousProcess::setStdOutBufferedSignalsEnabled(bool v)
+{
+ d->m_stdOut.bufferedSignalsEnabled = v;
+}
+
+bool SynchronousProcess::stdErrBufferedSignalsEnabled() const
+{
+ return d->m_stdErr.bufferedSignalsEnabled;
+}
+
+void SynchronousProcess::setStdErrBufferedSignalsEnabled(bool v)
+{
+ d->m_stdErr.bufferedSignalsEnabled = v;
+}
+
+Environment SynchronousProcess::environment() const
+{
+ return d->m_process.environment();
+}
+
+bool SynchronousProcess::timeOutMessageBoxEnabled() const
+{
+ return d->m_timeOutMessageBoxEnabled;
+}
+
+void SynchronousProcess::setTimeOutMessageBoxEnabled(bool v)
+{
+ d->m_timeOutMessageBoxEnabled = v;
+}
+
+void SynchronousProcess::setEnvironment(const Environment &e)
+{
+ d->m_process.setEnvironment(Environment(e));
+}
+
+void SynchronousProcess::setDisableUnixTerminal()
+{
+ d->m_process.setDisableUnixTerminal();
+}
+
+void SynchronousProcess::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter)
+{
+ QTC_ASSERT(interpreter, return);
+ d->m_exitCodeInterpreter = interpreter;
+}
+
+ExitCodeInterpreter SynchronousProcess::exitCodeInterpreter() const
+{
+ return d->m_exitCodeInterpreter;
+}
+
+void SynchronousProcess::setWorkingDirectory(const QString &workingDirectory)
+{
+ d->m_process.setWorkingDirectory(workingDirectory);
+}
+
+QString SynchronousProcess::workingDirectory() const
+{
+ return d->m_process.workingDirectory();
+}
+
+QProcess::ProcessChannelMode SynchronousProcess::processChannelMode () const
+{
+ return d->m_process.processChannelMode();
+}
+
+void SynchronousProcess::setProcessChannelMode(QProcess::ProcessChannelMode m)
+{
+ d->m_process.setProcessChannelMode(m);
+}
+
+#ifdef QT_GUI_LIB
+static bool isGuiThread()
+{
+ return QThread::currentThread() == QCoreApplication::instance()->thread();
+}
+#endif
+
+SynchronousProcessResponse SynchronousProcess::run(const CommandLine &cmd,
+ const QByteArray &writeData)
+{
+ // FIXME: Implement properly
+ if (cmd.executable().needsDevice()) {
+ QtcProcess proc;
+ proc.setEnvironment(Environment(d->m_process.environment()));
+ proc.setWorkingDirectory(d->m_process.workingDirectory());
+ proc.setCommand(cmd);
+
+ // writeData ?
+ proc.start();
+
+ proc.waitForFinished();
+
+ SynchronousProcessResponse res;
+ res.result = SynchronousProcessResponse::Finished;
+ res.exitCode = proc.exitCode();
+ res.rawStdOut = proc.readAllStandardOutput();
+ res.rawStdErr = proc.readAllStandardError();
+ return res;
+ };
+
+ qCDebug(processLog).noquote() << "Starting:" << cmd.toUserOutput();
+ ExecuteOnDestruction logResult([this] {
+ qCDebug(processLog) << d->m_result;
+ });
+
+ d->clearForRun();
+
+ d->m_binary = cmd.executable();
+ // using QProcess::start() and passing program, args and OpenMode results in a different
+ // quoting of arguments than using QProcess::setArguments() beforehand and calling start()
+ // only with the OpenMode
+ d->m_process.setCommand(cmd);
+ if (!writeData.isEmpty()) {
+ connect(&d->m_process, &QProcess::started, this, [this, writeData] {
+ d->m_process.write(writeData);
+ d->m_process.closeWriteChannel();
+ });
+ }
+ d->m_process.setOpenMode(writeData.isEmpty() ? QIODevice::ReadOnly : QIODevice::ReadWrite);
+ d->m_process.start();
+
+ // On Windows, start failure is triggered immediately if the
+ // executable cannot be found in the path. Do not start the
+ // event loop in that case.
+ if (!d->m_startFailure) {
+ d->m_timer.start();
+#ifdef QT_GUI_LIB
+ if (isGuiThread())
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+#endif
+ d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
+ processStdOut(false);
+ processStdErr(false);
+
+ d->m_result.rawStdOut = d->m_stdOut.rawData;
+ d->m_result.rawStdErr = d->m_stdErr.rawData;
+
+ d->m_timer.stop();
+#ifdef QT_GUI_LIB
+ if (isGuiThread())
+ QApplication::restoreOverrideCursor();
+#endif
+ }
+
+ return d->m_result;
+}
+
+SynchronousProcessResponse SynchronousProcess::runBlocking(const CommandLine &cmd)
+{
+ // FIXME: Implement properly
+ if (cmd.executable().needsDevice()) {
+ QtcProcess proc;
+ proc.setEnvironment(Environment(d->m_process.environment()));
+ proc.setWorkingDirectory(d->m_process.workingDirectory());
+ proc.setCommand(cmd);
+
+ // writeData ?
+ proc.start();
+
+ proc.waitForFinished();
+
+ SynchronousProcessResponse res;
+ res.result = SynchronousProcessResponse::Finished;
+ res.exitCode = proc.exitCode();
+ res.rawStdOut = proc.readAllStandardOutput();
+ res.rawStdErr = proc.readAllStandardError();
+ return res;
+ };
+
+ qCDebug(processLog).noquote() << "Starting blocking:" << cmd.toUserOutput();
+ ExecuteOnDestruction logResult([this] {
+ qCDebug(processLog) << d->m_result;
+ });
+
+ d->clearForRun();
+
+ d->m_binary = cmd.executable();
+ d->m_process.setOpenMode(QIODevice::ReadOnly);
+ d->m_process.setCommand(cmd);
+ d->m_process.start();
+ if (!d->m_process.waitForStarted(d->m_maxHangTimerCount * 1000)) {
+ d->m_result.result = SynchronousProcessResponse::StartFailed;
+ return d->m_result;
+ }
+ d->m_process.closeWriteChannel();
+ if (!d->m_process.waitForFinished(d->m_maxHangTimerCount * 1000)) {
+ d->m_result.result = SynchronousProcessResponse::Hang;
+ d->m_process.terminate();
+ if (!d->m_process.waitForFinished(1000)) {
+ d->m_process.kill();
+ d->m_process.waitForFinished(1000);
+ }
+ }
+
+ if (d->m_process.state() != QProcess::NotRunning)
+ return d->m_result;
+
+ d->m_result.exitCode = d->m_process.exitCode();
+ if (d->m_result.result == SynchronousProcessResponse::StartFailed) {
+ if (d->m_process.exitStatus() != QProcess::NormalExit)
+ d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
+ else
+ d->m_result.result = (exitCodeInterpreter())(d->m_result.exitCode);
+ }
+ processStdOut(false);
+ processStdErr(false);
+
+ d->m_result.rawStdOut = d->m_stdOut.rawData;
+ d->m_result.rawStdErr = d->m_stdErr.rawData;
+
+ return d->m_result;
+}
+
+bool SynchronousProcess::terminate()
+{
+ return d->m_process.stopProcess();
+}
+
+void SynchronousProcess::slotTimeout()
+{
+ if (!d->m_waitingForUser && (++d->m_hangTimerCount > d->m_maxHangTimerCount)) {
+ if (debug)
+ qDebug() << Q_FUNC_INFO << "HANG detected, killing";
+ d->m_waitingForUser = true;
+ const bool terminate = !d->m_timeOutMessageBoxEnabled || askToKill(d->m_binary.toString());
+ d->m_waitingForUser = false;
+ if (terminate) {
+ d->m_process.stopProcess();
+ d->m_result.result = SynchronousProcessResponse::Hang;
+ } else {
+ d->m_hangTimerCount = 0;
+ }
+ } else {
+ if (debug)
+ qDebug() << Q_FUNC_INFO << d->m_hangTimerCount;
+ }
+}
+
+void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << exitCode << e;
+ d->m_hangTimerCount = 0;
+
+ switch (e) {
+ case QProcess::NormalExit:
+ d->m_result.result = d->m_exitCodeInterpreter(exitCode);
+ d->m_result.exitCode = exitCode;
+ break;
+ case QProcess::CrashExit:
+ // Was hang detected before and killed?
+ if (d->m_result.result != SynchronousProcessResponse::Hang)
+ d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
+ d->m_result.exitCode = -1;
+ break;
+ }
+ d->m_eventLoop.quit();
+}
+
+void SynchronousProcess::error(QProcess::ProcessError e)
+{
+ d->m_hangTimerCount = 0;
+ if (debug)
+ qDebug() << Q_FUNC_INFO << e;
+ // Was hang detected before and killed?
+ if (d->m_result.result != SynchronousProcessResponse::Hang)
+ d->m_result.result = SynchronousProcessResponse::StartFailed;
+ d->m_startFailure = true;
+ d->m_eventLoop.quit();
+}
+
+void SynchronousProcess::processStdOut(bool emitSignals)
+{
+ // Handle binary data
+ d->m_stdOut.append(d->m_process.readAllStandardOutput(), emitSignals);
+}
+
+void SynchronousProcess::processStdErr(bool emitSignals)
+{
+ // Handle binary data
+ d->m_stdErr.append(d->m_process.readAllStandardError(), emitSignals);
+}
+
} // namespace Utils
+
+#include "qtcprocess.moc"
+
diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h
index d46bd41797..f16dd1764e 100644
--- a/src/libs/utils/qtcprocess.h
+++ b/src/libs/utils/qtcprocess.h
@@ -25,14 +25,61 @@
#pragma once
+#include "utils_global.h"
+
#include "environment.h"
#include <QProcess>
+#include <QTextCodec>
+
+#include <functional>
+
+QT_FORWARD_DECLARE_CLASS(QDebug)
namespace Utils {
+
class AbstractMacroExpander;
namespace Internal { class QtcProcessPrivate; }
+class SynchronousProcessPrivate;
+class CommandLine;
+class Environment;
+
+/* Result of SynchronousProcess execution */
+class QTCREATOR_UTILS_EXPORT SynchronousProcessResponse
+{
+public:
+ enum Result {
+ // Finished with return code 0
+ Finished,
+ // Finished with return code != 0
+ FinishedError,
+ // Process terminated abnormally (kill)
+ TerminatedAbnormally,
+ // Executable could not be started
+ StartFailed,
+ // Hang, no output after time out
+ Hang };
+
+ void clear();
+
+ // Helper to format an exit message.
+ QString exitMessage(const QString &binary, int timeoutS) const;
+
+ QByteArray allRawOutput() const;
+ QString allOutput() const;
+
+ QString stdOut() const;
+ QString stdErr() const;
+
+ Result result = StartFailed;
+ int exitCode = -1;
+
+ QByteArray rawStdOut;
+ QByteArray rawStdErr;
+ QTextCodec *codec = QTextCodec::codecForLocale();
+};
+
class QTCREATOR_UTILS_EXPORT QtcProcess : public QProcess
{
@@ -178,4 +225,70 @@ private:
QProcessEnvironment processEnvironment() const = delete;
};
+QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse &);
+
+using ExitCodeInterpreter = std::function<SynchronousProcessResponse::Result(int /*exitCode*/)>;
+QTCREATOR_UTILS_EXPORT SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code);
+
+class QTCREATOR_UTILS_EXPORT SynchronousProcess : public QObject
+{
+ Q_OBJECT
+public:
+ SynchronousProcess();
+ ~SynchronousProcess() override;
+
+ /* Timeout for hanging processes (triggers after no more output
+ * occurs on stderr/stdout). */
+ void setTimeoutS(int timeoutS);
+ int timeoutS() const;
+
+ void setCodec(QTextCodec *c);
+ QTextCodec *codec() const;
+
+ QProcess::ProcessChannelMode processChannelMode () const;
+ void setProcessChannelMode(QProcess::ProcessChannelMode m);
+
+ bool stdOutBufferedSignalsEnabled() const;
+ void setStdOutBufferedSignalsEnabled(bool);
+
+ bool stdErrBufferedSignalsEnabled() const;
+ void setStdErrBufferedSignalsEnabled(bool);
+
+ bool timeOutMessageBoxEnabled() const;
+ void setTimeOutMessageBoxEnabled(bool);
+
+ Environment environment() const;
+ void setEnvironment(const Environment &);
+
+ void setWorkingDirectory(const QString &workingDirectory);
+ QString workingDirectory() const;
+
+ // Unix: Do not give the child process a terminal for input prompting.
+ void setDisableUnixTerminal();
+
+ void setExitCodeInterpreter(const ExitCodeInterpreter &interpreter);
+ ExitCodeInterpreter exitCodeInterpreter() const;
+
+ // Starts a nested event loop and runs the command
+ SynchronousProcessResponse run(const CommandLine &cmd, const QByteArray &writeData = {});
+ // Starts the command blocking the UI fully
+ SynchronousProcessResponse runBlocking(const CommandLine &cmd);
+
+signals:
+ void stdOutBuffered(const QString &lines, bool firstTime);
+ void stdErrBuffered(const QString &lines, bool firstTime);
+
+public slots:
+ bool terminate();
+
+private:
+ void slotTimeout();
+ void finished(int exitCode, QProcess::ExitStatus e);
+ void error(QProcess::ProcessError);
+ void processStdOut(bool emitSignals);
+ void processStdErr(bool emitSignals);
+
+ SynchronousProcessPrivate *d;
+};
+
} // namespace Utils
diff --git a/src/libs/utils/shellcommand.h b/src/libs/utils/shellcommand.h
index 042a80eff5..5cf5a0c9f8 100644
--- a/src/libs/utils/shellcommand.h
+++ b/src/libs/utils/shellcommand.h
@@ -27,16 +27,13 @@
#include "utils_global.h"
-#include "synchronousprocess.h"
-
-#include <QObject>
+#include "qtcprocess.h"
#include <functional>
QT_BEGIN_NAMESPACE
class QMutex;
class QVariant;
-class QProcessEnvironment;
template <typename T>
class QFutureInterface;
template <typename T>
@@ -45,7 +42,6 @@ QT_END_NAMESPACE
namespace Utils {
-class CommandLine;
namespace Internal { class ShellCommandPrivate; }
class QTCREATOR_UTILS_EXPORT ProgressParser
diff --git a/src/libs/utils/synchronousprocess.cpp b/src/libs/utils/synchronousprocess.cpp
deleted file mode 100644
index 39a4bb9baf..0000000000
--- a/src/libs/utils/synchronousprocess.cpp
+++ /dev/null
@@ -1,591 +0,0 @@
-/****************************************************************************
-**
-** 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 "synchronousprocess.h"
-#include "executeondestruction.h"
-#include "hostosinfo.h"
-#include "qtcassert.h"
-#include "qtcprocess.h"
-
-#include <QDebug>
-#include <QDir>
-#include <QLoggingCategory>
-#include <QMessageBox>
-#include <QTextCodec>
-#include <QThread>
-#include <QTimer>
-
-#include <QApplication>
-
-#include <algorithm>
-#include <limits.h>
-#include <memory>
-
-/*!
- \class Utils::SynchronousProcess
-
- \brief The SynchronousProcess class runs a synchronous process in its own
- event loop that blocks only user input events. Thus, it allows for the GUI to
- repaint and append output to log windows.
-
- The stdOut(), stdErr() signals are emitted unbuffered as the process
- writes them.
-
- The stdOutBuffered(), stdErrBuffered() signals are emitted with complete
- lines based on the '\\n' marker if they are enabled using
- stdOutBufferedSignalsEnabled()/setStdErrBufferedSignalsEnabled().
- They would typically be used for log windows.
-
- There is a timeout handling that takes effect after the last data have been
- read from stdout/stdin (as opposed to waitForFinished(), which measures time
- since it was invoked). It is thus also suitable for slow processes that continously
- output data (like version system operations).
-
- The property timeOutMessageBoxEnabled influences whether a message box is
- shown asking the user if they want to kill the process on timeout (default: false).
-
- There are also static utility functions for dealing with fully synchronous
- processes, like reading the output with correct timeout handling.
-
- Caution: This class should NOT be used if there is a chance that the process
- triggers opening dialog boxes (for example, by file watchers triggering),
- as this will cause event loop problems.
-*/
-
-enum { debug = 0 };
-enum { syncDebug = 0 };
-
-enum { defaultMaxHangTimerCount = 10 };
-
-namespace Utils {
-
-static Q_LOGGING_CATEGORY(processLog, "qtc.utils.synchronousprocess", QtWarningMsg);
-
-// ----------- SynchronousProcessResponse
-void SynchronousProcessResponse::clear()
-{
- result = StartFailed;
- exitCode = -1;
- rawStdOut.clear();
- rawStdErr.clear();
-}
-
-QString SynchronousProcessResponse::exitMessage(const QString &binary, int timeoutS) const
-{
- switch (result) {
- case Finished:
- return SynchronousProcess::tr("The command \"%1\" finished successfully.").arg(QDir::toNativeSeparators(binary));
- case FinishedError:
- return SynchronousProcess::tr("The command \"%1\" terminated with exit code %2.").arg(QDir::toNativeSeparators(binary)).arg(exitCode);
- case TerminatedAbnormally:
- return SynchronousProcess::tr("The command \"%1\" terminated abnormally.").arg(QDir::toNativeSeparators(binary));
- case StartFailed:
- return SynchronousProcess::tr("The command \"%1\" could not be started.").arg(QDir::toNativeSeparators(binary));
- case Hang:
- return SynchronousProcess::tr("The command \"%1\" did not respond within the timeout limit (%2 s).")
- .arg(QDir::toNativeSeparators(binary)).arg(timeoutS);
- }
- return QString();
-}
-
-QByteArray SynchronousProcessResponse::allRawOutput() const
-{
- if (!rawStdOut.isEmpty() && !rawStdErr.isEmpty()) {
- QByteArray result = rawStdOut;
- if (!result.endsWith('\n'))
- result += '\n';
- result += rawStdErr;
- return result;
- }
- return !rawStdOut.isEmpty() ? rawStdOut : rawStdErr;
-}
-
-QString SynchronousProcessResponse::allOutput() const
-{
- const QString out = stdOut();
- const QString err = stdErr();
-
- if (!out.isEmpty() && !err.isEmpty()) {
- QString result = out;
- if (!result.endsWith('\n'))
- result += '\n';
- result += err;
- return result;
- }
- return !out.isEmpty() ? out : err;
-}
-
-QString SynchronousProcessResponse::stdOut() const
-{
- return QtcProcess::normalizeNewlines(codec->toUnicode(rawStdOut));
-}
-
-QString SynchronousProcessResponse::stdErr() const
-{
- return QtcProcess::normalizeNewlines(codec->toUnicode(rawStdErr));
-}
-
-QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse& r)
-{
- QDebug nsp = str.nospace();
- nsp << "SynchronousProcessResponse: result=" << r.result << " ex=" << r.exitCode << '\n'
- << r.rawStdOut.size() << " bytes stdout, stderr=" << r.rawStdErr << '\n';
- return str;
-}
-
-SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code)
-{
- return code ? SynchronousProcessResponse::FinishedError
- : SynchronousProcessResponse::Finished;
-}
-
-// Data for one channel buffer (stderr/stdout)
-class ChannelBuffer : public QObject
-{
- Q_OBJECT
-
-public:
- void clearForRun();
-
- QString linesRead();
- void append(const QByteArray &text, bool emitSignals);
-
- QByteArray rawData;
- QString incompleteLineBuffer; // lines not yet signaled
- QTextCodec *codec = nullptr; // Not owner
- std::unique_ptr<QTextCodec::ConverterState> codecState;
- int rawDataPos = 0;
- bool bufferedSignalsEnabled = false;
- bool firstBuffer = true;
-
-signals:
- void outputBuffered(const QString &text, bool firstTime);
-};
-
-void ChannelBuffer::clearForRun()
-{
- firstBuffer = true;
- rawDataPos = 0;
- rawData.clear();
- codecState.reset(new QTextCodec::ConverterState);
- incompleteLineBuffer.clear();
-}
-
-/* Check for complete lines read from the device and return them, moving the
- * buffer position. */
-QString ChannelBuffer::linesRead()
-{
- // Convert and append the new input to the buffer of incomplete lines
- const char *start = rawData.constData() + rawDataPos;
- const int len = rawData.size() - rawDataPos;
- incompleteLineBuffer.append(codec->toUnicode(start, len, codecState.get()));
- rawDataPos = rawData.size();
-
- // Any completed lines in the incompleteLineBuffer?
- const int lastLineIndex = qMax(incompleteLineBuffer.lastIndexOf('\n'),
- incompleteLineBuffer.lastIndexOf('\r'));
- if (lastLineIndex == -1)
- return QString();
-
- // Get completed lines and remove them from the incompleteLinesBuffer:
- const QString lines = QtcProcess::normalizeNewlines(incompleteLineBuffer.left(lastLineIndex + 1));
- incompleteLineBuffer = incompleteLineBuffer.mid(lastLineIndex + 1);
-
- return lines;
-}
-
-void ChannelBuffer::append(const QByteArray &text, bool emitSignals)
-{
- if (text.isEmpty())
- return;
- rawData += text;
- if (!emitSignals)
- return;
-
- // Buffered. Emit complete lines?
- if (bufferedSignalsEnabled) {
- const QString lines = linesRead();
- if (!lines.isEmpty()) {
- emit outputBuffered(lines, firstBuffer);
- firstBuffer = false;
- }
- }
-}
-
-// ----------- SynchronousProcessPrivate
-class SynchronousProcessPrivate {
-public:
- void clearForRun();
-
- QTextCodec *m_codec = QTextCodec::codecForLocale();
- QtcProcess m_process;
- QTimer m_timer;
- QEventLoop m_eventLoop;
- SynchronousProcessResponse m_result;
- FilePath m_binary;
- ChannelBuffer m_stdOut;
- ChannelBuffer m_stdErr;
- ExitCodeInterpreter m_exitCodeInterpreter = defaultExitCodeInterpreter;
-
- int m_hangTimerCount = 0;
- int m_maxHangTimerCount = defaultMaxHangTimerCount;
- bool m_startFailure = false;
- bool m_timeOutMessageBoxEnabled = false;
- bool m_waitingForUser = false;
-};
-
-void SynchronousProcessPrivate::clearForRun()
-{
- m_hangTimerCount = 0;
- m_stdOut.clearForRun();
- m_stdOut.codec = m_codec;
- m_stdErr.clearForRun();
- m_stdErr.codec = m_codec;
- m_result.clear();
- m_result.codec = m_codec;
- m_startFailure = false;
- m_binary = {};
-}
-
-// ----------- SynchronousProcess
-SynchronousProcess::SynchronousProcess() :
- d(new SynchronousProcessPrivate)
-{
- d->m_timer.setInterval(1000);
- connect(&d->m_timer, &QTimer::timeout, this, &SynchronousProcess::slotTimeout);
- connect(&d->m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
- this, &SynchronousProcess::finished);
- connect(&d->m_process, &QProcess::errorOccurred, this, &SynchronousProcess::error);
- connect(&d->m_process, &QProcess::readyReadStandardOutput,
- this, [this]() {
- d->m_hangTimerCount = 0;
- processStdOut(true);
- });
- connect(&d->m_process, &QProcess::readyReadStandardError,
- this, [this]() {
- d->m_hangTimerCount = 0;
- processStdErr(true);
- });
- connect(&d->m_stdOut, &ChannelBuffer::outputBuffered, this, &SynchronousProcess::stdOutBuffered);
- connect(&d->m_stdErr, &ChannelBuffer::outputBuffered, this, &SynchronousProcess::stdErrBuffered);
-}
-
-SynchronousProcess::~SynchronousProcess()
-{
- disconnect(&d->m_timer, nullptr, this, nullptr);
- disconnect(&d->m_process, nullptr, this, nullptr);
- delete d;
-}
-
-void SynchronousProcess::setTimeoutS(int timeoutS)
-{
- if (timeoutS > 0)
- d->m_maxHangTimerCount = qMax(2, timeoutS);
- else
- d->m_maxHangTimerCount = INT_MAX / 1000;
-}
-
-int SynchronousProcess::timeoutS() const
-{
- return d->m_maxHangTimerCount == (INT_MAX / 1000) ? -1 : d->m_maxHangTimerCount;
-}
-
-void SynchronousProcess::setCodec(QTextCodec *c)
-{
- QTC_ASSERT(c, return);
- d->m_codec = c;
-}
-
-QTextCodec *SynchronousProcess::codec() const
-{
- return d->m_codec;
-}
-
-bool SynchronousProcess::stdOutBufferedSignalsEnabled() const
-{
- return d->m_stdOut.bufferedSignalsEnabled;
-}
-
-void SynchronousProcess::setStdOutBufferedSignalsEnabled(bool v)
-{
- d->m_stdOut.bufferedSignalsEnabled = v;
-}
-
-bool SynchronousProcess::stdErrBufferedSignalsEnabled() const
-{
- return d->m_stdErr.bufferedSignalsEnabled;
-}
-
-void SynchronousProcess::setStdErrBufferedSignalsEnabled(bool v)
-{
- d->m_stdErr.bufferedSignalsEnabled = v;
-}
-
-Environment SynchronousProcess::environment() const
-{
- return d->m_process.environment();
-}
-
-bool SynchronousProcess::timeOutMessageBoxEnabled() const
-{
- return d->m_timeOutMessageBoxEnabled;
-}
-
-void SynchronousProcess::setTimeOutMessageBoxEnabled(bool v)
-{
- d->m_timeOutMessageBoxEnabled = v;
-}
-
-void SynchronousProcess::setEnvironment(const Environment &e)
-{
- d->m_process.setEnvironment(Environment(e));
-}
-
-void SynchronousProcess::setDisableUnixTerminal()
-{
- d->m_process.setDisableUnixTerminal();
-}
-
-void SynchronousProcess::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter)
-{
- QTC_ASSERT(interpreter, return);
- d->m_exitCodeInterpreter = interpreter;
-}
-
-ExitCodeInterpreter SynchronousProcess::exitCodeInterpreter() const
-{
- return d->m_exitCodeInterpreter;
-}
-
-void SynchronousProcess::setWorkingDirectory(const QString &workingDirectory)
-{
- d->m_process.setWorkingDirectory(workingDirectory);
-}
-
-QString SynchronousProcess::workingDirectory() const
-{
- return d->m_process.workingDirectory();
-}
-
-QProcess::ProcessChannelMode SynchronousProcess::processChannelMode () const
-{
- return d->m_process.processChannelMode();
-}
-
-void SynchronousProcess::setProcessChannelMode(QProcess::ProcessChannelMode m)
-{
- d->m_process.setProcessChannelMode(m);
-}
-
-static bool isGuiThread()
-{
- return QThread::currentThread() == QCoreApplication::instance()->thread();
-}
-
-SynchronousProcessResponse SynchronousProcess::run(const CommandLine &cmd,
- const QByteArray &writeData)
-{
- qCDebug(processLog).noquote() << "Starting:" << cmd.toUserOutput();
- ExecuteOnDestruction logResult([this] {
- qCDebug(processLog) << d->m_result;
- });
-
- d->clearForRun();
-
- d->m_binary = cmd.executable();
- // using QProcess::start() and passing program, args and OpenMode results in a different
- // quoting of arguments than using QProcess::setArguments() beforehand and calling start()
- // only with the OpenMode
- d->m_process.setCommand(cmd);
- if (!writeData.isEmpty()) {
- connect(&d->m_process, &QProcess::started, this, [this, writeData] {
- d->m_process.write(writeData);
- d->m_process.closeWriteChannel();
- });
- }
- d->m_process.setOpenMode(writeData.isEmpty() ? QIODevice::ReadOnly : QIODevice::ReadWrite);
- d->m_process.start();
-
- // On Windows, start failure is triggered immediately if the
- // executable cannot be found in the path. Do not start the
- // event loop in that case.
- if (!d->m_startFailure) {
- d->m_timer.start();
- if (isGuiThread())
- QApplication::setOverrideCursor(Qt::WaitCursor);
- d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
- processStdOut(false);
- processStdErr(false);
-
- d->m_result.rawStdOut = d->m_stdOut.rawData;
- d->m_result.rawStdErr = d->m_stdErr.rawData;
-
- d->m_timer.stop();
- if (isGuiThread())
- QApplication::restoreOverrideCursor();
- }
-
- return d->m_result;
-}
-
-SynchronousProcessResponse SynchronousProcess::runBlocking(const CommandLine &cmd)
-{
- qCDebug(processLog).noquote() << "Starting blocking:" << cmd.toUserOutput();
- ExecuteOnDestruction logResult([this] {
- qCDebug(processLog) << d->m_result;
- });
-
- d->clearForRun();
-
- d->m_binary = cmd.executable();
- d->m_process.setOpenMode(QIODevice::ReadOnly);
- d->m_process.setCommand(cmd);
- d->m_process.start();
- if (!d->m_process.waitForStarted(d->m_maxHangTimerCount * 1000)) {
- d->m_result.result = SynchronousProcessResponse::StartFailed;
- return d->m_result;
- }
- d->m_process.closeWriteChannel();
- if (!d->m_process.waitForFinished(d->m_maxHangTimerCount * 1000)) {
- d->m_result.result = SynchronousProcessResponse::Hang;
- d->m_process.terminate();
- if (!d->m_process.waitForFinished(1000)) {
- d->m_process.kill();
- d->m_process.waitForFinished(1000);
- }
- }
-
- if (d->m_process.state() != QProcess::NotRunning)
- return d->m_result;
-
- d->m_result.exitCode = d->m_process.exitCode();
- if (d->m_result.result == SynchronousProcessResponse::StartFailed) {
- if (d->m_process.exitStatus() != QProcess::NormalExit)
- d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
- else
- d->m_result.result = (exitCodeInterpreter())(d->m_result.exitCode);
- }
- processStdOut(false);
- processStdErr(false);
-
- d->m_result.rawStdOut = d->m_stdOut.rawData;
- d->m_result.rawStdErr = d->m_stdErr.rawData;
-
- return d->m_result;
-}
-
-bool SynchronousProcess::terminate()
-{
- return d->m_process.stopProcess();
-}
-
-static inline bool askToKill(const QString &binary = QString())
-{
- if (!isGuiThread())
- return true;
- const QString title = SynchronousProcess::tr("Process not Responding");
- QString msg = binary.isEmpty() ?
- SynchronousProcess::tr("The process is not responding.") :
- SynchronousProcess::tr("The process \"%1\" is not responding.").arg(QDir::toNativeSeparators(binary));
- msg += QLatin1Char(' ');
- msg += SynchronousProcess::tr("Would you like to terminate it?");
- // Restore the cursor that is set to wait while running.
- const bool hasOverrideCursor = QApplication::overrideCursor() != nullptr;
- if (hasOverrideCursor)
- QApplication::restoreOverrideCursor();
- QMessageBox::StandardButton answer = QMessageBox::question(nullptr, title, msg, QMessageBox::Yes|QMessageBox::No);
- if (hasOverrideCursor)
- QApplication::setOverrideCursor(Qt::WaitCursor);
- return answer == QMessageBox::Yes;
-}
-
-void SynchronousProcess::slotTimeout()
-{
- if (!d->m_waitingForUser && (++d->m_hangTimerCount > d->m_maxHangTimerCount)) {
- if (debug)
- qDebug() << Q_FUNC_INFO << "HANG detected, killing";
- d->m_waitingForUser = true;
- const bool terminate = !d->m_timeOutMessageBoxEnabled || askToKill(d->m_binary.toString());
- d->m_waitingForUser = false;
- if (terminate) {
- d->m_process.stopProcess();
- d->m_result.result = SynchronousProcessResponse::Hang;
- } else {
- d->m_hangTimerCount = 0;
- }
- } else {
- if (debug)
- qDebug() << Q_FUNC_INFO << d->m_hangTimerCount;
- }
-}
-
-void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e)
-{
- if (debug)
- qDebug() << Q_FUNC_INFO << exitCode << e;
- d->m_hangTimerCount = 0;
-
- switch (e) {
- case QProcess::NormalExit:
- d->m_result.result = d->m_exitCodeInterpreter(exitCode);
- d->m_result.exitCode = exitCode;
- break;
- case QProcess::CrashExit:
- // Was hang detected before and killed?
- if (d->m_result.result != SynchronousProcessResponse::Hang)
- d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
- d->m_result.exitCode = -1;
- break;
- }
- d->m_eventLoop.quit();
-}
-
-void SynchronousProcess::error(QProcess::ProcessError e)
-{
- d->m_hangTimerCount = 0;
- if (debug)
- qDebug() << Q_FUNC_INFO << e;
- // Was hang detected before and killed?
- if (d->m_result.result != SynchronousProcessResponse::Hang)
- d->m_result.result = SynchronousProcessResponse::StartFailed;
- d->m_startFailure = true;
- d->m_eventLoop.quit();
-}
-
-void SynchronousProcess::processStdOut(bool emitSignals)
-{
- // Handle binary data
- d->m_stdOut.append(d->m_process.readAllStandardOutput(), emitSignals);
-}
-
-void SynchronousProcess::processStdErr(bool emitSignals)
-{
- // Handle binary data
- d->m_stdErr.append(d->m_process.readAllStandardError(), emitSignals);
-}
-
-} // namespace Utils
-
-#include "synchronousprocess.moc"
diff --git a/src/libs/utils/synchronousprocess.h b/src/libs/utils/synchronousprocess.h
deleted file mode 100644
index 3117cc85e2..0000000000
--- a/src/libs/utils/synchronousprocess.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/****************************************************************************
-**
-** 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 "utils_global.h"
-
-#include <QProcess>
-#include <QTextCodec>
-
-#include <functional>
-
-QT_FORWARD_DECLARE_CLASS(QDebug)
-
-namespace Utils {
-
-class SynchronousProcessPrivate;
-class CommandLine;
-class Environment;
-
-/* Result of SynchronousProcess execution */
-class QTCREATOR_UTILS_EXPORT SynchronousProcessResponse
-{
-public:
- enum Result {
- // Finished with return code 0
- Finished,
- // Finished with return code != 0
- FinishedError,
- // Process terminated abnormally (kill)
- TerminatedAbnormally,
- // Executable could not be started
- StartFailed,
- // Hang, no output after time out
- Hang };
-
- void clear();
-
- // Helper to format an exit message.
- QString exitMessage(const QString &binary, int timeoutS) const;
-
- QByteArray allRawOutput() const;
- QString allOutput() const;
-
- QString stdOut() const;
- QString stdErr() const;
-
- Result result = StartFailed;
- int exitCode = -1;
-
- QByteArray rawStdOut;
- QByteArray rawStdErr;
- QTextCodec *codec = QTextCodec::codecForLocale();
-};
-
-QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse &);
-
-using ExitCodeInterpreter = std::function<SynchronousProcessResponse::Result(int /*exitCode*/)>;
-QTCREATOR_UTILS_EXPORT SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code);
-
-class QTCREATOR_UTILS_EXPORT SynchronousProcess : public QObject
-{
- Q_OBJECT
-public:
- SynchronousProcess();
- ~SynchronousProcess() override;
-
- /* Timeout for hanging processes (triggers after no more output
- * occurs on stderr/stdout). */
- void setTimeoutS(int timeoutS);
- int timeoutS() const;
-
- void setCodec(QTextCodec *c);
- QTextCodec *codec() const;
-
- QProcess::ProcessChannelMode processChannelMode () const;
- void setProcessChannelMode(QProcess::ProcessChannelMode m);
-
- bool stdOutBufferedSignalsEnabled() const;
- void setStdOutBufferedSignalsEnabled(bool);
-
- bool stdErrBufferedSignalsEnabled() const;
- void setStdErrBufferedSignalsEnabled(bool);
-
- bool timeOutMessageBoxEnabled() const;
- void setTimeOutMessageBoxEnabled(bool);
-
- Environment environment() const;
- void setEnvironment(const Environment &);
-
- void setWorkingDirectory(const QString &workingDirectory);
- QString workingDirectory() const;
-
- // Unix: Do not give the child process a terminal for input prompting.
- void setDisableUnixTerminal();
-
- void setExitCodeInterpreter(const ExitCodeInterpreter &interpreter);
- ExitCodeInterpreter exitCodeInterpreter() const;
-
- // Starts a nested event loop and runs the command
- SynchronousProcessResponse run(const CommandLine &cmd, const QByteArray &writeData = {});
- // Starts the command blocking the UI fully
- SynchronousProcessResponse runBlocking(const CommandLine &cmd);
-
-signals:
- void stdOutBuffered(const QString &lines, bool firstTime);
- void stdErrBuffered(const QString &lines, bool firstTime);
-
-public slots:
- bool terminate();
-
-private:
- void slotTimeout();
- void finished(int exitCode, QProcess::ExitStatus e);
- void error(QProcess::ProcessError);
- void processStdOut(bool emitSignals);
- void processStdErr(bool emitSignals);
-
- SynchronousProcessPrivate *d;
-};
-
-} // namespace Utils
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index fb829bde6c..2d8162746a 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -60,7 +60,6 @@ SOURCES += \
$$PWD/classnamevalidatinglineedit.cpp \
$$PWD/fancylineedit.cpp \
$$PWD/qtcolorbutton.cpp \
- $$PWD/synchronousprocess.cpp \
$$PWD/savefile.cpp \
$$PWD/fileutils.cpp \
$$PWD/textfileformat.cpp \
@@ -188,7 +187,6 @@ HEADERS += \
$$PWD/fancylineedit.h \
$$PWD/qtcolorbutton.h \
$$PWD/consoleprocess.h \
- $$PWD/synchronousprocess.h \
$$PWD/savefile.h \
$$PWD/fileutils.h \
$$PWD/textfileformat.h \
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index faeda9174c..a7da48d811 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -263,8 +263,6 @@ Project {
"styledbar.h",
"stylehelper.cpp",
"stylehelper.h",
- "synchronousprocess.cpp",
- "synchronousprocess.h",
"templateengine.cpp",
"templateengine.h",
"temporarydirectory.cpp",
diff --git a/src/plugins/android/androidavdmanager.cpp b/src/plugins/android/androidavdmanager.cpp
index 086b1da11b..1d98ea6c03 100644
--- a/src/plugins/android/androidavdmanager.cpp
+++ b/src/plugins/android/androidavdmanager.cpp
@@ -22,16 +22,19 @@
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
+
#include "androidavdmanager.h"
#include "avdmanageroutputparser.h"
#include <coreplugin/icore.h>
+
#include <projectexplorer/projectexplorerconstants.h>
+
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
-#include <utils/synchronousprocess.h>
#include <QApplication>
#include <QFileInfo>
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index d2af119b18..c05af5eb3f 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -59,7 +59,6 @@
#include <utils/infolabel.h>
#include <utils/pathchooser.h>
#include <utils/qtcprocess.h>
-#include <utils/synchronousprocess.h>
#include <QCheckBox>
#include <QComboBox>
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 4e13e9cc72..3251a0834a 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -57,9 +57,9 @@
#include <utils/hostosinfo.h>
#include <utils/persistentsettings.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
#include <QApplication>
#include <QDirIterator>
diff --git a/src/plugins/android/androidcreatekeystorecertificate.cpp b/src/plugins/android/androidcreatekeystorecertificate.cpp
index 2417abf5a5..38405468b1 100644
--- a/src/plugins/android/androidcreatekeystorecertificate.cpp
+++ b/src/plugins/android/androidcreatekeystorecertificate.cpp
@@ -27,7 +27,7 @@
#include "androidconfigurations.h"
#include "ui_androidcreatekeystorecertificate.h"
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QFileDialog>
#include <QRegularExpression>
diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp
index b8a822b30b..8b49d82ef3 100644
--- a/src/plugins/android/androiddeployqtstep.cpp
+++ b/src/plugins/android/androiddeployqtstep.cpp
@@ -55,7 +55,6 @@
#include <utils/layoutbuilder.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <utils/synchronousprocess.h>
#include <QCheckBox>
#include <QFileDialog>
diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp
index f77bfa6d1e..33bdf5e1ac 100644
--- a/src/plugins/android/androidmanager.cpp
+++ b/src/plugins/android/androidmanager.cpp
@@ -53,8 +53,8 @@
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
#include <QApplication>
#include <QDir>
diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp
index d23f37b2f7..90aebfb7d1 100644
--- a/src/plugins/android/androidrunnerworker.cpp
+++ b/src/plugins/android/androidrunnerworker.cpp
@@ -47,7 +47,6 @@
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
#include <utils/temporaryfile.h>
#include <utils/url.h>
diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp
index 7f105ecbe0..3afdc157dd 100644
--- a/src/plugins/android/androidsdkmanager.cpp
+++ b/src/plugins/android/androidsdkmanager.cpp
@@ -34,7 +34,6 @@
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
#include <QFutureWatcher>
#include <QLoggingCategory>
diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp
index 51b837af0f..6f22e28c43 100644
--- a/src/plugins/android/androidsettingswidget.cpp
+++ b/src/plugins/android/androidsettingswidget.cpp
@@ -45,7 +45,6 @@
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <utils/synchronousprocess.h>
#include <utils/utilsicons.h>
#include <QDesktopServices>
diff --git a/src/plugins/baremetal/iarewtoolchain.cpp b/src/plugins/baremetal/iarewtoolchain.cpp
index 6338dee137..5ae78f83d7 100644
--- a/src/plugins/baremetal/iarewtoolchain.cpp
+++ b/src/plugins/baremetal/iarewtoolchain.cpp
@@ -38,7 +38,6 @@
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <utils/synchronousprocess.h>
#include <QDebug>
#include <QDir>
diff --git a/src/plugins/baremetal/keiltoolchain.cpp b/src/plugins/baremetal/keiltoolchain.cpp
index 9432039f4d..77da384443 100644
--- a/src/plugins/baremetal/keiltoolchain.cpp
+++ b/src/plugins/baremetal/keiltoolchain.cpp
@@ -38,7 +38,6 @@
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <utils/synchronousprocess.h>
#include <QDebug>
#include <QDir>
diff --git a/src/plugins/baremetal/sdcctoolchain.cpp b/src/plugins/baremetal/sdcctoolchain.cpp
index 5d53ba18b7..3c6a8b377c 100644
--- a/src/plugins/baremetal/sdcctoolchain.cpp
+++ b/src/plugins/baremetal/sdcctoolchain.cpp
@@ -37,7 +37,7 @@
#include <utils/environment.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QDebug>
#include <QDir>
diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
index bc4079d1e5..81b3b26c56 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
+++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
@@ -33,7 +33,7 @@
#include <utils/runextensions.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QDateTime>
#include <QFile>
diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp
index f67495396c..534de41ce0 100644
--- a/src/plugins/beautifier/beautifierplugin.cpp
+++ b/src/plugins/beautifier/beautifierplugin.cpp
@@ -53,8 +53,8 @@
#include <utils/fileutils.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
-#include <utils/synchronousprocess.h>
#include <utils/temporarydirectory.h>
#include <utils/textutils.h>
diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
index db538328e6..542feff2a0 100644
--- a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
+++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
@@ -31,7 +31,7 @@
#include <coreplugin/icore.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QDateTime>
#include <QFile>
diff --git a/src/plugins/clangtools/clangtidyclazyrunner.cpp b/src/plugins/clangtools/clangtidyclazyrunner.cpp
index b8f55e8374..3d3e83115a 100644
--- a/src/plugins/clangtools/clangtidyclazyrunner.cpp
+++ b/src/plugins/clangtools/clangtidyclazyrunner.cpp
@@ -34,8 +34,8 @@
#include <cpptools/compileroptionsbuilder.h>
#include <cpptools/cpptoolsreuse.h>
-#include <utils/synchronousprocess.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QDebug>
#include <QDir>
diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp
index 78eb5764ca..464fe6388b 100644
--- a/src/plugins/clangtools/clangtoolrunner.cpp
+++ b/src/plugins/clangtools/clangtoolrunner.cpp
@@ -29,7 +29,7 @@
#include <utils/environment.h>
#include <utils/qtcassert.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <utils/temporaryfile.h>
#include <QDebug>
diff --git a/src/plugins/clangtools/clangtoolsutils.cpp b/src/plugins/clangtools/clangtoolsutils.cpp
index 4a32165786..ed09f84127 100644
--- a/src/plugins/clangtools/clangtoolsutils.cpp
+++ b/src/plugins/clangtools/clangtoolsutils.cpp
@@ -35,11 +35,10 @@
#include <cpptools/cpptoolsreuse.h>
#include <projectexplorer/projectexplorerconstants.h>
-#include <utils/qtcprocess.h>
#include <utils/checkablemessagebox.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QFileInfo>
diff --git a/src/plugins/clangtools/executableinfo.cpp b/src/plugins/clangtools/executableinfo.cpp
index 795c6f0e1d..e663c0edcb 100644
--- a/src/plugins/clangtools/executableinfo.cpp
+++ b/src/plugins/clangtools/executableinfo.cpp
@@ -29,7 +29,7 @@
#include <coreplugin/messagemanager.h>
#include <utils/environment.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QDir>
#include <QFileInfo>
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index 8b0589b533..1f18766034 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -60,9 +60,9 @@
#include <utils/infobar.h>
#include <utils/parameteraction.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
#include <utils/temporarydirectory.h>
#include <vcsbase/basevcseditorfactory.h>
diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h
index 12a71c546c..ada086d1da 100644
--- a/src/plugins/cmakeprojectmanager/cmaketool.h
+++ b/src/plugins/cmakeprojectmanager/cmaketool.h
@@ -32,7 +32,7 @@
#include <utils/fileutils.h>
#include <utils/id.h>
#include <utils/optional.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
QT_FORWARD_DECLARE_CLASS(QProcess)
diff --git a/src/plugins/coreplugin/plugininstallwizard.cpp b/src/plugins/coreplugin/plugininstallwizard.cpp
index 91230b658e..60ae9b49b1 100644
--- a/src/plugins/coreplugin/plugininstallwizard.cpp
+++ b/src/plugins/coreplugin/plugininstallwizard.cpp
@@ -36,8 +36,8 @@
#include <utils/infolabel.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
-#include <utils/synchronousprocess.h>
#include <utils/temporarydirectory.h>
#include <utils/wizard.h>
#include <utils/wizardpage.h>
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index 8e90d3de18..3e7c12f85b 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -42,9 +42,9 @@
#include <texteditor/textdocument.h>
-#include <utils/synchronousprocess.h>
#include <utils/parameteraction.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <coreplugin/icore.h>
diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp
index c324fe0361..be54dd0aad 100644
--- a/src/plugins/debugger/debuggeritem.cpp
+++ b/src/plugins/debugger/debuggeritem.cpp
@@ -35,8 +35,8 @@
#include <utils/hostosinfo.h>
#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
#include <utils/utilsicons.h>
#include <utils/winutils.h>
diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp
index 350393affe..c69f792564 100644
--- a/src/plugins/debugger/debuggeritemmanager.cpp
+++ b/src/plugins/debugger/debuggeritemmanager.cpp
@@ -43,7 +43,7 @@
#include <utils/pathchooser.h>
#include <utils/persistentsettings.h>
#include <utils/qtcassert.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <utils/treemodel.h>
#include <utils/winutils.h>
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index d365d2685a..01a17f383b 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -64,7 +64,6 @@
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
#include <utils/temporaryfile.h>
#include <QDirIterator>
diff --git a/src/plugins/git/gerrit/gerritserver.cpp b/src/plugins/git/gerrit/gerritserver.cpp
index a0a6a65046..eca26f7bd8 100644
--- a/src/plugins/git/gerrit/gerritserver.cpp
+++ b/src/plugins/git/gerrit/gerritserver.cpp
@@ -31,8 +31,9 @@
#include <coreplugin/icore.h>
#include <coreplugin/shellcommand.h>
+
#include <utils/hostosinfo.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QFile>
#include <QJsonDocument>
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 4e75d7f6db..4e83d0b442 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -50,7 +50,6 @@
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
#include <utils/temporaryfile.h>
#include <utils/theme/theme.h>
diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp
index 79c035cd72..4cc0d37110 100644
--- a/src/plugins/git/gitgrep.cpp
+++ b/src/plugins/git/gitgrep.cpp
@@ -39,8 +39,8 @@
#include <utils/filesearch.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
-#include <utils/synchronousprocess.h>
#include <utils/textfileformat.h>
#include <QCheckBox>
diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp
index 2997b37120..ef6652fb9e 100644
--- a/src/plugins/ios/iosconfigurations.cpp
+++ b/src/plugins/ios/iosconfigurations.cpp
@@ -31,10 +31,7 @@
#include "iosprobe.h"
#include <coreplugin/icore.h>
-#include <utils/algorithm.h>
-#include <utils/synchronousprocess.h>
-#include <utils/qtcassert.h>
-#include <utils/synchronousprocess.h>
+
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/devicesupport/devicemanager.h>
@@ -42,14 +39,20 @@
#include <projectexplorer/toolchain.h>
#include <projectexplorer/gcctoolchain.h>
#include <projectexplorer/projectexplorerconstants.h>
+
#include <debugger/debuggeritemmanager.h>
#include <debugger/debuggeritem.h>
#include <debugger/debuggerkitinformation.h>
+
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtversionmanager.h>
#include <qtsupport/qtversionfactory.h>
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+
#include <QDir>
#include <QDomDocument>
#include <QFileInfo>
diff --git a/src/plugins/ios/iosprobe.cpp b/src/plugins/ios/iosprobe.cpp
index 66518ad778..12d5daae0d 100644
--- a/src/plugins/ios/iosprobe.cpp
+++ b/src/plugins/ios/iosprobe.cpp
@@ -26,7 +26,7 @@
#include "iosprobe.h"
#include <utils/algorithm.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QDir>
#include <QFileInfo>
diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp
index a63fdb9dfa..0d84f28c47 100644
--- a/src/plugins/ios/iostoolhandler.cpp
+++ b/src/plugins/ios/iostoolhandler.cpp
@@ -29,12 +29,14 @@
#include "iossimulator.h"
#include "simulatorcontrol.h"
-#include "debugger/debuggerconstants.h"
#include <coreplugin/icore.h>
-#include <utils/qtcassert.h>
+
+#include <debugger/debuggerconstants.h>
+
#include <utils/fileutils.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
-#include <utils/synchronousprocess.h>
#include <QCoreApplication>
#include <QDir>
diff --git a/src/plugins/ios/simulatorcontrol.cpp b/src/plugins/ios/simulatorcontrol.cpp
index 19dbe3c1bb..b2464a3307 100644
--- a/src/plugins/ios/simulatorcontrol.cpp
+++ b/src/plugins/ios/simulatorcontrol.cpp
@@ -29,7 +29,7 @@
#include <utils/algorithm.h>
#include <utils/runextensions.h>
#include <utils/qtcassert.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#ifdef Q_OS_MAC
#include <CoreFoundation/CoreFoundation.h>
diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp
index dc49f17a47..404cef6d45 100644
--- a/src/plugins/languageclient/client.cpp
+++ b/src/plugins/languageclient/client.cpp
@@ -34,6 +34,8 @@
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <coreplugin/messagemanager.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+
#include <languageserverprotocol/completion.h>
#include <languageserverprotocol/diagnostics.h>
#include <languageserverprotocol/languagefeatures.h>
@@ -41,8 +43,10 @@
#include <languageserverprotocol/servercapabilities.h>
#include <languageserverprotocol/workspace.h>
#include <languageserverprotocol/progresssupport.h>
+
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
+
#include <texteditor/codeassist/documentcontentcompletion.h>
#include <texteditor/codeassist/iassistprocessor.h>
#include <texteditor/ioutlinewidget.h>
@@ -52,10 +56,10 @@
#include <texteditor/texteditor.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorsettings.h>
+
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcprocess.h>
-#include <utils/synchronousprocess.h>
-#include <coreplugin/progressmanager/progressmanager.h>
+
#include <QDebug>
#include <QLoggingCategory>
diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp
index 60238fd65f..92708ac56d 100644
--- a/src/plugins/mercurial/mercurialclient.cpp
+++ b/src/plugins/mercurial/mercurialclient.cpp
@@ -35,10 +35,11 @@
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseeditorconfig.h>
#include <vcsbase/vcsbasediffeditorcontroller.h>
-#include <utils/synchronousprocess.h>
+
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QDateTime>
#include <QDir>
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index aa797b865d..bc293bbb09 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -41,11 +41,13 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/locator/commandlocator.h>
+
#include <texteditor/textdocument.h>
+
#include <utils/fileutils.h>
#include <utils/parameteraction.h>
#include <utils/qtcassert.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <utils/temporarydirectory.h>
#include <vcsbase/basevcseditorfactory.h>
diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
index 1f8a7c0130..3a1595c089 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
@@ -29,7 +29,7 @@
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <utils/temporarydirectory.h>
#include <QFileInfo>
diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp
index 89dc87e65c..65b01ee898 100644
--- a/src/plugins/projectexplorer/gcctoolchain.cpp
+++ b/src/plugins/projectexplorer/gcctoolchain.cpp
@@ -37,11 +37,9 @@
#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
-#include <utils/synchronousprocess.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <utils/synchronousprocess.h>
#include <QBuffer>
#include <QComboBox>
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index 4e91b8b599..8ca498f73c 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -40,7 +40,6 @@
#include <utils/optional.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <utils/synchronousprocess.h>
#include <utils/runextensions.h>
#include <utils/temporarydirectory.h>
#include <utils/pathchooser.h>
diff --git a/src/plugins/python/pythonsettings.cpp b/src/plugins/python/pythonsettings.cpp
index 5b1b8e119a..ffe8b83e02 100644
--- a/src/plugins/python/pythonsettings.cpp
+++ b/src/plugins/python/pythonsettings.cpp
@@ -28,7 +28,7 @@
#include "pythonconstants.h"
#include <coreplugin/dialogs/ioptionspage.h>
-#include "coreplugin/icore.h"
+#include <coreplugin/icore.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
@@ -37,7 +37,7 @@
#include <utils/listmodel.h>
#include <utils/layoutbuilder.h>
#include <utils/pathchooser.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <utils/treemodel.h>
#include <QDir>
diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp
index 5f89ec14cf..7854935ff8 100644
--- a/src/plugins/python/pythonutils.cpp
+++ b/src/plugins/python/pythonutils.cpp
@@ -48,7 +48,6 @@
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
-#include <utils/synchronousprocess.h>
#include <QDir>
#include <QFutureWatcher>
diff --git a/src/plugins/subversion/subversionclient.cpp b/src/plugins/subversion/subversionclient.cpp
index 2f1d930184..2a21a2d51b 100644
--- a/src/plugins/subversion/subversionclient.cpp
+++ b/src/plugins/subversion/subversionclient.cpp
@@ -28,20 +28,22 @@
#include "subversionplugin.h"
#include "subversionsettings.h"
+#include <coreplugin/editormanager/editormanager.h>
+
#include <vcsbase/vcscommand.h>
#include <vcsbase/vcsbaseconstants.h>
#include <vcsbase/vcsbasediffeditorcontroller.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseeditorconfig.h>
#include <vcsbase/vcsbaseplugin.h>
-#include <utils/qtcassert.h>
-#include <utils/synchronousprocess.h>
+
#include <diffeditor/diffeditorcontroller.h>
#include <diffeditor/diffutils.h>
-#include <coreplugin/editormanager/editormanager.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QDir>
#include <QFileInfo>
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index 6e71ab3d6d..fa16f7180b 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -57,8 +57,8 @@
#include <utils/hostosinfo.h>
#include <utils/parameteraction.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
#include <QDebug>
#include <QDir>
diff --git a/src/plugins/texteditor/formattexteditor.cpp b/src/plugins/texteditor/formattexteditor.cpp
index 54655de390..2b41d3ef0a 100644
--- a/src/plugins/texteditor/formattexteditor.cpp
+++ b/src/plugins/texteditor/formattexteditor.cpp
@@ -32,11 +32,11 @@
#include <coreplugin/messagemanager.h>
#include <utils/differ.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
-#include <utils/synchronousprocess.h>
#include <utils/temporarydirectory.h>
#include <utils/textutils.h>
-#include <utils/qtcassert.h>
#include <QFileInfo>
#include <QFutureWatcher>
diff --git a/src/plugins/texteditor/highlightersettings.cpp b/src/plugins/texteditor/highlightersettings.cpp
index 97d31ba999..765b30e958 100644
--- a/src/plugins/texteditor/highlightersettings.cpp
+++ b/src/plugins/texteditor/highlightersettings.cpp
@@ -31,8 +31,8 @@
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
-#include <utils/synchronousprocess.h>
#include <QSettings>
#include <QLatin1String>
diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp
index 9efee40788..c5ee483cee 100644
--- a/src/plugins/vcsbase/vcsbaseclient.cpp
+++ b/src/plugins/vcsbase/vcsbaseclient.cpp
@@ -36,7 +36,7 @@
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
-#include <utils/synchronousprocess.h>
+
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsoutputwindow.h>
#include <vcsbase/vcsbaseplugin.h>
diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h
index 708eb174ff..dc532a31ec 100644
--- a/src/plugins/vcsbase/vcsbaseclient.h
+++ b/src/plugins/vcsbase/vcsbaseclient.h
@@ -31,7 +31,7 @@
#include <utils/fileutils.h>
#include <utils/id.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QObject>
#include <QStringList>
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index 421c6ea819..031115a245 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -38,7 +38,7 @@
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <utils/qtcassert.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QDebug>
#include <QDir>
diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp
index 01b4df2f1c..bbed7be63b 100644
--- a/tests/auto/debugger/tst_dumpers.cpp
+++ b/tests/auto/debugger/tst_dumpers.cpp
@@ -32,12 +32,6 @@
#include <utils/environment.h>
#include <utils/qtcprocess.h>
-#ifdef Q_OS_WIN
-#ifdef Q_CC_MSVC
-#include <utils/synchronousprocess.h>
-#endif // Q_CC_MSVC
-#endif // Q_OS_WIN
-
#include <QtTest>
#include <math.h>
diff --git a/tests/manual/process/mainwindow.cpp b/tests/manual/process/mainwindow.cpp
index 85a7b2ef9f..addd95e5a7 100644
--- a/tests/manual/process/mainwindow.cpp
+++ b/tests/manual/process/mainwindow.cpp
@@ -26,7 +26,7 @@
#include "mainwindow.h"
#include <utils/fileutils.h>
-#include <utils/synchronousprocess.h>
+#include <utils/qtcprocess.h>
#include <QPlainTextEdit>
#include <QApplication>