diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp
index 71a30aa91b5ac308b9fa753bf63bee9b7ef24187..a57c829a22177e7c7f29d71712de42d928f301e5 100644
--- a/src/libs/utils/buildablehelperlibrary.cpp
+++ b/src/libs/utils/buildablehelperlibrary.cpp
@@ -40,24 +40,22 @@ bool BuildableHelperLibrary::isQtChooser(const QFileInfo &info)
 
 QString BuildableHelperLibrary::qtChooserToQmakePath(const QString &path)
 {
-    const char toolDir[] = "QTTOOLDIR=\"";
-    QProcess proc;
-    proc.start(path, QStringList(QLatin1String("-print-env")));
-    if (!proc.waitForStarted(1000))
-        return QString();
-    if (!proc.waitForFinished(1000))
+    const QString toolDir = QLatin1String("QTTOOLDIR=\"");
+    SynchronousProcess proc;
+    proc.setTimeoutS(1);
+    SynchronousProcessResponse response = proc.run(path, QStringList(QLatin1String("-print-env")));
+    if (response.result != SynchronousProcessResponse::Finished)
         return QString();
-    QByteArray output = proc.readAllStandardOutput();
+    const QString output = response.stdOut;
     int pos = output.indexOf(toolDir);
     if (pos == -1)
         return QString();
-    pos += int(sizeof(toolDir)) - 1;
+    pos += toolDir.count() - 1;
     int end = output.indexOf('\"', pos);
     if (end == -1)
         return QString();
 
-    QString result = QString::fromLocal8Bit(output.mid(pos, end - pos)) + QLatin1String("/qmake");
-    return result;
+    return output.mid(pos, end - pos) + QLatin1String("/qmake");
 }
 
 static bool isQmake(const QString &path)
@@ -104,23 +102,15 @@ QString BuildableHelperLibrary::qtVersionForQMake(const QString &qmakePath)
     if (qmakePath.isEmpty())
         return QString();
 
-    QProcess qmake;
-    qmake.start(qmakePath, QStringList(QLatin1String("--version")));
-    if (!qmake.waitForStarted()) {
-        qWarning("Cannot start '%s': %s", qPrintable(qmakePath), qPrintable(qmake.errorString()));
-        return QString();
-    }
-    if (!qmake.waitForFinished())      {
-        SynchronousProcess::stopProcess(qmake);
-        qWarning("Timeout running '%s'.", qPrintable(qmakePath));
-        return QString();
-    }
-    if (qmake.exitStatus() != QProcess::NormalExit) {
-        qWarning("'%s' crashed.", qPrintable(qmakePath));
+    SynchronousProcess qmake;
+    qmake.setTimeoutS(5);
+    SynchronousProcessResponse response = qmake.run(qmakePath, QStringList(QLatin1String("--version")));
+    if (response.result != SynchronousProcessResponse::Finished) {
+        qWarning() << response.exitMessage(qmakePath, 5);
         return QString();
     }
 
-    const QString output = QString::fromLocal8Bit(qmake.readAllStandardOutput());
+    const QString output = response.allOutput();
     static QRegExp regexp(QLatin1String("(QMake version|QMake version:)[\\s]*([\\d.]*)"),
                           Qt::CaseInsensitive);
     regexp.indexIn(output);
diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp
index 565da03c6a1275d111bb4c5132566d6bb5265338..0b17543f93b0a3cdbbadbe63398e68d1072d89ff 100644
--- a/src/libs/utils/consoleprocess_unix.cpp
+++ b/src/libs/utils/consoleprocess_unix.cpp
@@ -211,7 +211,7 @@ void ConsoleProcess::stop()
     killStub();
     if (isRunning()) {
         d->m_process.terminate();
-        if (!d->m_process.waitForFinished(1000)) {
+        if (!d->m_process.waitForFinished(1000) && d->m_process.state() == QProcess::Running) {
             d->m_process.kill();
             d->m_process.waitForFinished();
         }
diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp
index 9246366b68ec4412ee899b413ccd723abb42fefe..3ee32339368c1688d0bf7a6780b95d4e8068e642 100644
--- a/src/libs/utils/pathchooser.cpp
+++ b/src/libs/utils/pathchooser.cpp
@@ -129,16 +129,12 @@ QString BinaryVersionToolTipEventFilter::toolVersion(const QString &binary, cons
 {
     if (binary.isEmpty())
         return QString();
-    QProcess proc;
-    proc.start(binary, arguments);
-    if (!proc.waitForStarted())
+    SynchronousProcess proc;
+    proc.setTimeoutS(1);
+    SynchronousProcessResponse response = proc.run(binary, arguments);
+    if (response.result != SynchronousProcessResponse::Finished)
         return QString();
-    if (!proc.waitForFinished()) {
-        SynchronousProcess::stopProcess(proc);
-        return QString();
-    }
-    return QString::fromLocal8Bit(QByteArray(proc.readAllStandardOutput()
-        + proc.readAllStandardError()));
+    return response.allOutput();
 }
 
 // Extends BinaryVersionToolTipEventFilter to prepend the existing pathchooser
diff --git a/src/libs/utils/synchronousprocess.cpp b/src/libs/utils/synchronousprocess.cpp
index 5b5d433f45267b67a4bc69506138de6920eb5dd6..42b32bacbdee7e9eb2546590b261cce4c0c22632 100644
--- a/src/libs/utils/synchronousprocess.cpp
+++ b/src/libs/utils/synchronousprocess.cpp
@@ -137,6 +137,17 @@ QString SynchronousProcessResponse::exitMessage(const QString &binary, int timeo
     return QString();
 }
 
+QString SynchronousProcessResponse::allOutput() const
+{
+    if (!stdOut.isEmpty() && !stdErr.isEmpty()) {
+        if (stdOut.endsWith(QLatin1Char('\n')))
+            return stdOut + stdErr;
+        else
+            return stdOut + QLatin1Char('\n') + stdErr;
+    }
+    return !stdOut.isEmpty() ? stdOut : stdErr;
+}
+
 QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse& r)
 {
     QDebug nsp = str.nospace();
@@ -579,9 +590,8 @@ bool SynchronousProcess::readDataFromProcess(QProcess &p, int timeoutS,
     bool finished = false;
     bool hasData = false;
     do {
-        finished = p.state() == QProcess::NotRunning
-                || p.waitForFinished(timeoutS > 0 ? timeoutS * 1000 : -1);
-        hasData = false;
+        finished = p.waitForFinished(timeoutS > 0 ? timeoutS * 1000 : -1)
+                || p.state() == QProcess::NotRunning;
         // First check 'stdout'
         if (p.bytesAvailable()) { // applies to readChannel() only
             hasData = true;
@@ -608,13 +618,13 @@ bool SynchronousProcess::readDataFromProcess(QProcess &p, int timeoutS,
 
 bool SynchronousProcess::stopProcess(QProcess &p)
 {
-    if (p.state() != QProcess::Running)
+    if (p.state() == QProcess::NotRunning)
         return true;
     p.terminate();
-    if (p.waitForFinished(300))
+    if (p.waitForFinished(300) && p.state() == QProcess::Running)
         return true;
     p.kill();
-    return p.waitForFinished(300);
+    return p.waitForFinished(300) || p.state() == QProcess::NotRunning;
 }
 
 // Path utilities
diff --git a/src/libs/utils/synchronousprocess.h b/src/libs/utils/synchronousprocess.h
index e11fc052bc89d943f4851e56fb08d2d5edb5950c..352705dfaefab889a9d0aeee842ba6d4794b0dbd 100644
--- a/src/libs/utils/synchronousprocess.h
+++ b/src/libs/utils/synchronousprocess.h
@@ -59,6 +59,7 @@ struct QTCREATOR_UTILS_EXPORT SynchronousProcessResponse
 
     // Helper to format an exit message.
     QString exitMessage(const QString &binary, int timeoutS) const;
+    QString allOutput() const;
 
     Result result;
     int exitCode;
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index 7883df405f926fdf6c799f759abd9b8ad836d6d7..698dc98aa08d732911df6211d822de24e45e5187 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -43,10 +43,11 @@
 
 #include <qtsupport/qtkitinformation.h>
 
-#include <utils/qtcprocess.h>
+#include <utils/synchronousprocess.h>
 
 #include <QInputDialog>
 #include <QMessageBox>
+#include <QProcess>
 
 namespace Android {
 using namespace Internal;
@@ -279,29 +280,32 @@ bool AndroidBuildApkStep::verboseOutput() const
 QAbstractItemModel *AndroidBuildApkStep::keystoreCertificates()
 {
     QString rawCerts;
-    QProcess keytoolProc;
     while (!rawCerts.length() || !m_keystorePasswd.length()) {
-        QStringList params;
-        params << QLatin1String("-list") << QLatin1String("-v") << QLatin1String("-keystore") << m_keystorePath.toUserOutput() << QLatin1String("-storepass");
+        QStringList params
+                = { QLatin1String("-list"), QLatin1String("-v"), QLatin1String("-keystore"),
+                    m_keystorePath.toUserOutput(), QLatin1String("-storepass") };
         if (!m_keystorePasswd.length())
             keystorePassword();
         if (!m_keystorePasswd.length())
-            return 0;
+            return nullptr;
         params << m_keystorePasswd;
         params << QLatin1String("-J-Duser.language=en");
-        keytoolProc.start(AndroidConfigurations::currentConfig().keytoolPath().toString(), params);
-        if (!keytoolProc.waitForStarted() || !keytoolProc.waitForFinished()) {
+
+        Utils::SynchronousProcess keytoolProc;
+        keytoolProc.setTimeoutS(30);
+        const Utils::SynchronousProcessResponse response
+                = keytoolProc.run(AndroidConfigurations::currentConfig().keytoolPath().toString(), params);
+        if (response.result != Utils::SynchronousProcessResponse::Finished) {
             QMessageBox::critical(0, tr("Error"),
                                   tr("Failed to run keytool."));
-            return 0;
+            return nullptr;
         }
 
-        if (keytoolProc.exitCode()) {
-            QMessageBox::critical(0, tr("Error"),
-                                  tr("Invalid password."));
+        if (response.exitCode != 0) {
+            QMessageBox::critical(0, tr("Error"), tr("Invalid password."));
             m_keystorePasswd.clear();
         }
-        rawCerts = QString::fromLatin1(keytoolProc.readAllStandardOutput());
+        rawCerts = response.stdOut;
     }
     return new CertificatesModel(rawCerts, this);
 }
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 06ace3cb36194d12fd002850d20d4e7f419d84dd..32b4596a09bb8417848fe2b1bef86af7ad1324c7 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -49,8 +49,10 @@
 #include <qtsupport/qtversionmanager.h>
 #include <utils/algorithm.h>
 #include <utils/environment.h>
+#include <utils/qtcassert.h>
 #include <utils/runextensions.h>
 #include <utils/sleep.h>
+#include <utils/synchronousprocess.h>
 
 #include <QDateTime>
 #include <QSettings>
@@ -153,16 +155,13 @@ namespace {
                 if (executable.isEmpty() || shell.isEmpty())
                     return true; // we can't detect, but creator is 32bit so assume 32bit
 
-                QProcess proc;
+                SynchronousProcess proc;
                 proc.setProcessChannelMode(QProcess::MergedChannels);
-                proc.start(executable, QStringList() << shell);
-                if (!proc.waitForFinished(2000)) {
-                    proc.kill();
+                proc.setTimeoutS(30);
+                SynchronousProcessResponse response = proc.run(executable, QStringList() << shell);
+                if (response.result != SynchronousProcessResponse::Finished)
                     return true;
-                }
-                if (proc.readAll().contains("x86-64"))
-                    return false;
-                return true;
+                return !response.allOutput().contains("x86-64");
             }
         }
         return false;
@@ -391,17 +390,16 @@ void AndroidConfig::updateAvailableSdkPlatforms() const
         return;
     m_availableSdkPlatforms.clear();
 
-    QProcess proc;
+    SynchronousProcess proc;
     proc.setProcessEnvironment(androidToolEnvironment().toProcessEnvironment());
-    proc.start(androidToolPath().toString(), QStringList() << QLatin1String("list") << QLatin1String("target")); // list avaialbe AVDs
-    if (!proc.waitForFinished(10000)) {
-        proc.terminate();
+    SynchronousProcessResponse response
+            = proc.run(androidToolPath().toString(), QStringList() << QLatin1String("list") << QLatin1String("target")); // list avaialbe AVDs
+    if (response.result == SynchronousProcessResponse::Finished)
         return;
-    }
 
     SdkPlatform platform;
-    while (proc.canReadLine()) {
-        const QString line = QString::fromLocal8Bit(proc.readLine().trimmed());
+    foreach (const QString &l, response.allOutput().split('\n')) {
+        const QString line = l.trimmed();
         if (line.startsWith(QLatin1String("id:")) && line.contains(QLatin1String("android-"))) {
             int index = line.indexOf(QLatin1String("\"android-"));
             if (index == -1)
@@ -551,17 +549,18 @@ QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
 QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(const QString &adbToolPath, QString *error)
 {
     QVector<AndroidDeviceInfo> devices;
-    QProcess adbProc;
-    adbProc.start(adbToolPath, QStringList() << QLatin1String("devices"));
-    if (!adbProc.waitForFinished(10000)) {
-        adbProc.kill();
+    SynchronousProcess adbProc;
+    adbProc.setTimeoutS(30);
+    SynchronousProcessResponse response
+            = adbProc.run(adbToolPath, QStringList() << QLatin1String("devices"));
+    if (response.result != SynchronousProcessResponse::Finished) {
         if (error)
             *error = QApplication::translate("AndroidConfiguration",
                                              "Could not run: %1")
                 .arg(adbToolPath + QLatin1String(" devices"));
         return devices;
     }
-    QList<QByteArray> adbDevs = adbProc.readAll().trimmed().split('\n');
+    QStringList adbDevs = response.allOutput().split('\n');
     if (adbDevs.empty())
         return devices;
 
@@ -571,9 +570,9 @@ QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(const QString &adbToo
 
     // workaround for '????????????' serial numbers:
     // can use "adb -d" when only one usb device attached
-    foreach (const QByteArray &device, adbDevs) {
-        const QString serialNo = QString::fromLatin1(device.left(device.indexOf('\t')).trimmed());
-        const QString deviceType = QString::fromLatin1(device.mid(device.indexOf('\t'))).trimmed();
+    foreach (const QString &device, adbDevs) {
+        const QString serialNo = device.left(device.indexOf('\t')).trimmed();
+        const QString deviceType = device.mid(device.indexOf('\t')).trimmed();
         if (isBootToQt(adbToolPath, serialNo))
             continue;
         AndroidDeviceInfo dev;
@@ -642,7 +641,7 @@ AndroidConfig::CreateAvdInfo AndroidConfig::createAVDImpl(CreateAvdInfo info, Fi
                 .arg(androidToolPath.toString(), arguments.join(QLatin1Char(' ')));
         return info;
     }
-
+    QTC_CHECK(proc.state() == QProcess::Running);
     proc.write(QByteArray("yes\n")); // yes to "Do you wish to create a custom hardware profile"
 
     QByteArray question;
@@ -664,8 +663,7 @@ AndroidConfig::CreateAvdInfo AndroidConfig::createAVDImpl(CreateAvdInfo info, Fi
         if (proc.state() != QProcess::Running)
             break;
     }
-
-    proc.waitForFinished();
+    QTC_CHECK(proc.state() == QProcess::NotRunning);
 
     QString errorOutput = QString::fromLocal8Bit(proc.readAllStandardError());
     // The exit code is always 0, so we need to check stderr
@@ -679,16 +677,14 @@ AndroidConfig::CreateAvdInfo AndroidConfig::createAVDImpl(CreateAvdInfo info, Fi
 
 bool AndroidConfig::removeAVD(const QString &name) const
 {
-    QProcess proc;
+    SynchronousProcess proc;
+    proc.setTimeoutS(5);
     proc.setProcessEnvironment(androidToolEnvironment().toProcessEnvironment());
-    proc.start(androidToolPath().toString(),
-               QStringList() << QLatin1String("delete") << QLatin1String("avd")
-               << QLatin1String("-n") << name);
-    if (!proc.waitForFinished(5000)) {
-        proc.terminate();
-        return false;
-    }
-    return !proc.exitCode();
+    SynchronousProcessResponse response
+            = proc.run(androidToolPath().toString(),
+                       QStringList() << QLatin1String("delete") << QLatin1String("avd")
+                       << QLatin1String("-n") << name);
+    return response.result == SynchronousProcessResponse::Finished && response.exitCode == 0;
 }
 
 QFuture<QVector<AndroidDeviceInfo>> AndroidConfig::androidVirtualDevicesFuture() const
@@ -700,19 +696,20 @@ QFuture<QVector<AndroidDeviceInfo>> AndroidConfig::androidVirtualDevicesFuture()
 QVector<AndroidDeviceInfo> AndroidConfig::androidVirtualDevices(const QString &androidTool, const Environment &environment)
 {
     QVector<AndroidDeviceInfo> devices;
-    QProcess proc;
+    SynchronousProcess proc;
+    proc.setTimeoutS(20);
     proc.setProcessEnvironment(environment.toProcessEnvironment());
-    proc.start(androidTool,
-               QStringList() << QLatin1String("list") << QLatin1String("avd")); // list available AVDs
-    if (!proc.waitForFinished(20000)) {
-        proc.terminate();
+    SynchronousProcessResponse response
+            = proc.run(androidTool,
+                       QStringList() << QLatin1String("list") << QLatin1String("avd")); // list available AVDs
+    if (response.result != SynchronousProcessResponse::Finished)
         return devices;
-    }
-    QList<QByteArray> avds = proc.readAll().trimmed().split('\n');
+
+    QStringList avds = response.allOutput().split('\n');
     if (avds.empty())
         return devices;
 
-    while (avds.first().startsWith("* daemon"))
+    while (avds.first().startsWith(QLatin1String("* daemon")))
         avds.removeFirst(); // remove the daemon logs
     avds.removeFirst(); // remove "List of devices attached" header line
 
@@ -720,7 +717,7 @@ QVector<AndroidDeviceInfo> AndroidConfig::androidVirtualDevices(const QString &a
 
     AndroidDeviceInfo dev;
     for (int i = 0; i < avds.size(); i++) {
-        QString line = QLatin1String(avds.at(i));
+        QString line = avds.at(i);
         if (!line.contains(QLatin1String("Name:")))
             continue;
 
@@ -732,7 +729,7 @@ QVector<AndroidDeviceInfo> AndroidConfig::androidVirtualDevices(const QString &a
         dev.cpuAbi.clear();
         ++i;
         for (; i < avds.size(); ++i) {
-            line = QLatin1String(avds[i]);
+            line = avds.at(i);
             if (line.contains(QLatin1String("---------")))
                 break;
 
@@ -870,13 +867,11 @@ bool AndroidConfig::isBootToQt(const QString &adbToolPath, const QString &device
     arguments << QLatin1String("shell")
               << QLatin1String("ls -l /system/bin/appcontroller || ls -l /usr/bin/appcontroller && echo Boot2Qt");
 
-    QProcess adbProc;
-    adbProc.start(adbToolPath, arguments);
-    if (!adbProc.waitForFinished(10000)) {
-        adbProc.kill();
-        return false;
-    }
-    return adbProc.readAll().contains("Boot2Qt");
+    SynchronousProcess adbProc;
+    adbProc.setTimeoutS(10);
+    SynchronousProcessResponse response = adbProc.run(adbToolPath, arguments);
+    return response.result == SynchronousProcessResponse::Finished
+            && response.allOutput().contains(QLatin1String("Boot2Qt"));
 }
 
 
@@ -884,17 +879,15 @@ QString AndroidConfig::getDeviceProperty(const QString &adbToolPath, const QStri
 {
     // workaround for '????????????' serial numbers
     QStringList arguments = AndroidDeviceInfo::adbSelector(device);
-    arguments << QLatin1String("shell") << QLatin1String("getprop")
-              << property;
+    arguments << QLatin1String("shell") << QLatin1String("getprop") << property;
 
-    QProcess adbProc;
-    adbProc.start(adbToolPath, arguments);
-    if (!adbProc.waitForFinished(10000)) {
-        adbProc.kill();
+    SynchronousProcess adbProc;
+    adbProc.setTimeoutS(10);
+    SynchronousProcessResponse response = adbProc.run(adbToolPath, arguments);
+    if (response.result != SynchronousProcessResponse::Finished)
         return QString();
-    }
 
-    return QString::fromLocal8Bit(adbProc.readAll());
+    return response.allOutput();
 }
 
 int AndroidConfig::getSDKVersion(const QString &device) const
@@ -988,16 +981,13 @@ bool AndroidConfig::hasFinishedBooting(const QString &device) const
     arguments << QLatin1String("shell") << QLatin1String("getprop")
               << QLatin1String("init.svc.bootanim");
 
-    QProcess adbProc;
-    adbProc.start(adbToolPath().toString(), arguments);
-    if (!adbProc.waitForFinished(10000)) {
-        adbProc.kill();
+    SynchronousProcess adbProc;
+    adbProc.setTimeoutS(10);
+    SynchronousProcessResponse response = adbProc.run(adbToolPath().toString(), arguments);
+    if (response.result != SynchronousProcessResponse::Finished)
         return false;
-    }
-    QString value = QString::fromLocal8Bit(adbProc.readAll().trimmed());
-    if (value == QLatin1String("stopped"))
-        return true;
-    return false;
+    QString value = response.allOutput().trimmed();
+    return value == QLatin1String("stopped");
 }
 
 QStringList AndroidConfig::getAbis(const QString &device) const
@@ -1010,15 +1000,14 @@ QStringList AndroidConfig::getAbis(const QString &adbToolPath, const QString &de
     QStringList result;
     // First try via ro.product.cpu.abilist
     QStringList arguments = AndroidDeviceInfo::adbSelector(device);
-    arguments << QLatin1String("shell") << QLatin1String("getprop");
-    arguments << QLatin1String("ro.product.cpu.abilist");
-    QProcess adbProc;
-    adbProc.start(adbToolPath, arguments);
-    if (!adbProc.waitForFinished(10000)) {
-        adbProc.kill();
+    arguments << QLatin1String("shell") << QLatin1String("getprop") << QLatin1String("ro.product.cpu.abilist");
+    SynchronousProcess adbProc;
+    adbProc.setTimeoutS(10);
+    SynchronousProcessResponse response = adbProc.run(adbToolPath, arguments);
+    if (response.result != SynchronousProcessResponse::Finished)
         return result;
-    }
-    QString output = QString::fromLocal8Bit(adbProc.readAll().trimmed());
+
+    QString output = response.allOutput().trimmed();
     if (!output.isEmpty()) {
         QStringList result = output.split(QLatin1Char(','));
         if (!result.isEmpty())
@@ -1034,13 +1023,13 @@ QStringList AndroidConfig::getAbis(const QString &adbToolPath, const QString &de
         else
             arguments << QString::fromLatin1("ro.product.cpu.abi%1").arg(i);
 
-        QProcess adbProc;
-        adbProc.start(adbToolPath, arguments);
-        if (!adbProc.waitForFinished(10000)) {
-            adbProc.kill();
+        SynchronousProcess abiProc;
+        abiProc.setTimeoutS(10);
+        SynchronousProcessResponse abiResponse = abiProc.run(adbToolPath, arguments);
+        if (abiResponse.result != SynchronousProcessResponse::Finished)
             return result;
-        }
-        QString abi = QString::fromLocal8Bit(adbProc.readAll().trimmed());
+
+        QString abi = abiResponse.allOutput().trimmed();
         if (abi.isEmpty())
             break;
         result << abi;
@@ -1483,13 +1472,12 @@ void AndroidConfigurations::load()
         } else if (HostOsInfo::isMacHost()) {
             QFileInfo javaHomeExec(QLatin1String("/usr/libexec/java_home"));
             if (javaHomeExec.isExecutable() && !javaHomeExec.isDir()) {
-                QProcess proc;
+                SynchronousProcess proc;
+                proc.setTimeoutS(2);
                 proc.setProcessChannelMode(QProcess::MergedChannels);
-                proc.start(javaHomeExec.absoluteFilePath());
-                if (!proc.waitForFinished(2000)) {
-                    proc.kill();
-                } else {
-                    const QString &javaHome = QString::fromLocal8Bit(proc.readAll().trimmed());
+                SynchronousProcessResponse response = proc.run(javaHomeExec.absoluteFilePath(), QStringList());
+                if (response.result == SynchronousProcessResponse::Finished) {
+                    const QString &javaHome = response.allOutput().trimmed();
                     if (!javaHome.isEmpty() && QFileInfo::exists(javaHome))
                         m_config.setOpenJDKLocation(FileName::fromString(javaHome));
                 }
diff --git a/src/plugins/android/androidcreatekeystorecertificate.cpp b/src/plugins/android/androidcreatekeystorecertificate.cpp
index 764ce3c8345f06c060d76b40458c211109959e60..70c9dc9d92ce641d02541c80cf74b1dd83972188 100644
--- a/src/plugins/android/androidcreatekeystorecertificate.cpp
+++ b/src/plugins/android/androidcreatekeystorecertificate.cpp
@@ -27,8 +27,9 @@
 #include "androidconfigurations.h"
 #include "ui_androidcreatekeystorecertificate.h"
 
+#include <utils/synchronousprocess.h>
+
 #include <QFileDialog>
-#include <QProcess>
 #include <QMessageBox>
 
 using namespace Android::Internal;
@@ -162,6 +163,7 @@ void AndroidCreateKeystoreCertificate::on_buttonBox_accepted()
     if (ui->stateNameLineEdit->text().length())
         distinguishedNames += QLatin1String(", S=") + ui->stateNameLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,"));
 
+    const QString command = AndroidConfigurations::currentConfig().keytoolPath().toString();
     QStringList params;
     params << QLatin1String("-genkey") << QLatin1String("-keyalg") << QLatin1String("RSA")
            << QLatin1String("-keystore") << m_keystoreFilePath.toString()
@@ -172,16 +174,13 @@ void AndroidCreateKeystoreCertificate::on_buttonBox_accepted()
            << QLatin1String("-keypass") << certificatePassword()
            << QLatin1String("-dname") << distinguishedNames;
 
-    QProcess genKeyCertProc;
-    genKeyCertProc.start(AndroidConfigurations::currentConfig().keytoolPath().toString(), params );
-
-    if (!genKeyCertProc.waitForStarted() || !genKeyCertProc.waitForFinished())
-        return;
+    Utils::SynchronousProcess genKeyCertProc;
+    genKeyCertProc.setTimeoutS(15);
+    Utils::SynchronousProcessResponse response = genKeyCertProc.run(command, params);
 
-    if (genKeyCertProc.exitCode()) {
-        QMessageBox::critical(this, tr("Error")
-                              , QString::fromLatin1(genKeyCertProc.readAllStandardOutput())
-                              + QString::fromLatin1(genKeyCertProc.readAllStandardError()));
+    if (response.result != Utils::SynchronousProcessResponse::Finished || response.exitCode != 0) {
+        QMessageBox::critical(this, tr("Error"),
+                              response.exitMessage(command, 15) + QLatin1Char('\n') + response.allOutput());
         return;
     }
     accept();
diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp
index 7a5f6b6deeab9ca6a048cb3e3106549c185c81fb..062c13e7a4fcc670098892c836e29b0ff0ab3f60 100644
--- a/src/plugins/android/androiddeployqtstep.cpp
+++ b/src/plugins/android/androiddeployqtstep.cpp
@@ -50,6 +50,7 @@
 #include <utils/algorithm.h>
 #include <utils/qtcassert.h>
 #include <utils/qtcprocess.h>
+#include <utils/synchronousprocess.h>
 
 #include <QInputDialog>
 #include <QMessageBox>
@@ -354,7 +355,10 @@ AndroidDeployQtStep::DeployResult AndroidDeployQtStep::runDeploy(QFutureInterfac
                    .arg(QDir::toNativeSeparators(m_command), args),
                    BuildStep::MessageOutput);
 
-    while (m_process->state() != QProcess::NotRunning && !m_process->waitForFinished(200)) {
+    while (!m_process->waitForFinished(200)) {
+        if (m_process->state() == QProcess::NotRunning)
+            break;
+
         if (fi.isCanceled()) {
             m_process->kill();
             m_process->waitForFinished();
@@ -464,25 +468,12 @@ void AndroidDeployQtStep::run(QFutureInterface<bool> &fi)
 
 void AndroidDeployQtStep::runCommand(const QString &program, const QStringList &arguments)
 {
-    QProcess buildProc;
+    Utils::SynchronousProcess buildProc;
+    buildProc.setTimeoutS(2 * 60);
     emit addOutput(tr("Package deploy: Running command \"%1 %2\".").arg(program).arg(arguments.join(QLatin1Char(' '))), BuildStep::MessageOutput);
-    buildProc.start(program, arguments);
-    if (!buildProc.waitForStarted()) {
-        emit addOutput(tr("Packaging error: Could not start command \"%1 %2\". Reason: %3")
-            .arg(program).arg(arguments.join(QLatin1Char(' '))).arg(buildProc.errorString()), BuildStep::ErrorMessageOutput);
-        return;
-    }
-    if (!buildProc.waitForFinished(2 * 60 * 1000)
-            || buildProc.error() != QProcess::UnknownError
-            || buildProc.exitCode() != 0) {
-        QString mainMessage = tr("Packaging error: Command \"%1 %2\" failed.")
-                .arg(program).arg(arguments.join(QLatin1Char(' ')));
-        if (buildProc.error() != QProcess::UnknownError)
-            mainMessage += QLatin1Char(' ') + tr("Reason: %1").arg(buildProc.errorString());
-        else
-            mainMessage += tr("Exit code: %1").arg(buildProc.exitCode());
-        emit addOutput(mainMessage, BuildStep::ErrorMessageOutput);
-    }
+    Utils::SynchronousProcessResponse response = buildProc.run(program, arguments);
+    if (response.result != Utils::SynchronousProcessResponse::Finished || response.exitCode != 0)
+        emit addOutput(response.exitMessage(program, 2 * 60), BuildStep::ErrorMessageOutput);
 }
 
 AndroidDeviceInfo AndroidDeployQtStep::deviceInfo() const
diff --git a/src/plugins/android/androiddeployqtstep.h b/src/plugins/android/androiddeployqtstep.h
index 470b8a411590691e10dfaea5a06152a90d28be38..cfb8f69bd554b85602d572bf1d0ea73b0c8f0053 100644
--- a/src/plugins/android/androiddeployqtstep.h
+++ b/src/plugins/android/androiddeployqtstep.h
@@ -32,9 +32,7 @@
 #include <projectexplorer/abstractprocessstep.h>
 #include <qtsupport/baseqtversion.h>
 
-namespace Utils {
-class QtcProcess;
-}
+namespace Utils { class QtcProcess; }
 
 QT_BEGIN_NAMESPACE
 class QAbstractItemModel;
diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp
index d35a1998e38eb42ae14537ce370721c55e2e53ba..a8a778cd3980f0f1255e14c34f86832e284bc204 100644
--- a/src/plugins/android/androidmanager.cpp
+++ b/src/plugins/android/androidmanager.cpp
@@ -51,6 +51,7 @@
 #include <qtsupport/qtkitinformation.h>
 #include <qtsupport/qtsupportconstants.h>
 #include <utils/algorithm.h>
+#include <utils/synchronousprocess.h>
 
 #include <QDir>
 #include <QFileSystemWatcher>
@@ -345,13 +346,13 @@ void AndroidManager::installQASIPackage(ProjectExplorer::Target *target, const Q
     QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber);
     arguments << QLatin1String("install") << QLatin1String("-r ") << packagePath;
 
-    process->connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater()));
+    connect(process, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
+            process, &QObject::deleteLater);
     const QString adb = AndroidConfigurations::currentConfig().adbToolPath().toString();
     Core::MessageManager::write(adb + QLatin1Char(' ') + arguments.join(QLatin1Char(' ')));
     process->start(adb, arguments);
-    if (!process->waitForFinished(500))
+    if (!process->waitForStarted(500) && process->state() != QProcess::Running)
         delete process;
-
 }
 
 bool AndroidManager::checkKeystorePassword(const QString &keystorePath, const QString &keystorePasswd)
@@ -364,16 +365,10 @@ bool AndroidManager::checkKeystorePassword(const QString &keystorePath, const QS
               << keystorePath
               << QLatin1String("--storepass")
               << keystorePasswd;
-    QProcess proc;
-    proc.start(AndroidConfigurations::currentConfig().keytoolPath().toString(), arguments);
-    if (!proc.waitForStarted(10000))
-        return false;
-    if (!proc.waitForFinished(10000)) {
-        proc.kill();
-        proc.waitForFinished();
-        return false;
-    }
-    return proc.exitCode() == 0;
+    Utils::SynchronousProcess proc;
+    proc.setTimeoutS(10);
+    Utils::SynchronousProcessResponse response = proc.run(AndroidConfigurations::currentConfig().keytoolPath().toString(), arguments);
+    return (response.result == Utils::SynchronousProcessResponse::Finished && response.exitCode == 0);
 }
 
 bool AndroidManager::checkCertificatePassword(const QString &keystorePath, const QString &keystorePasswd, const QString &alias, const QString &certificatePasswd)
@@ -393,16 +388,11 @@ bool AndroidManager::checkCertificatePassword(const QString &keystorePath, const
     else
         arguments << certificatePasswd;
 
-    QProcess proc;
-    proc.start(AndroidConfigurations::currentConfig().keytoolPath().toString(), arguments);
-    if (!proc.waitForStarted(10000))
-        return false;
-    if (!proc.waitForFinished(10000)) {
-        proc.kill();
-        proc.waitForFinished();
-        return false;
-    }
-    return proc.exitCode() == 0;
+    Utils::SynchronousProcess proc;
+    proc.setTimeoutS(10);
+    Utils::SynchronousProcessResponse response
+            = proc.run(AndroidConfigurations::currentConfig().keytoolPath().toString(), arguments);
+    return response.result == Utils::SynchronousProcessResponse::Finished && response.exitCode == 0;
 }
 
 bool AndroidManager::checkForQt51Files(Utils::FileName fileName)
diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp
index 2d5e5b579f98ee70ef2c62fd51117870fd60b6e0..ec29ca4b5bc83890b7c3bf5fcc7271ad25f61997 100644
--- a/src/plugins/android/androidrunner.cpp
+++ b/src/plugins/android/androidrunner.cpp
@@ -37,6 +37,7 @@
 #include <qtsupport/qtkitinformation.h>
 #include <utils/qtcassert.h>
 #include <utils/runextensions.h>
+#include <utils/synchronousprocess.h>
 
 #include <QApplication>
 #include <QDir>
@@ -169,10 +170,11 @@ AndroidRunner::AndroidRunner(QObject *parent,
 
 
     // Detect busybox, as we need to pass -w to ps to get wide output.
-    QProcess psProc;
-    psProc.start(m_adb, selector() << _("shell") << _("readlink") << _("$(which ps)"));
-    psProc.waitForFinished();
-    QByteArray which = psProc.readAll();
+    Utils::SynchronousProcess psProc;
+    psProc.setTimeoutS(5);
+    Utils::SynchronousProcessResponse response
+            = psProc.run(m_adb, selector() << _("shell") << _("readlink") << _("$(which ps)"));
+    const QString which = response.allOutput();
     m_isBusyBox = which.startsWith("busybox");
 
     m_checkPIDTimer.setInterval(1000);
@@ -302,10 +304,8 @@ void AndroidRunner::checkPID()
 
 void AndroidRunner::forceStop()
 {
-    QProcess proc;
-    proc.start(m_adb, selector() << _("shell") << _("am") << _("force-stop")
-               << m_androidRunnable.packageName);
-    proc.waitForFinished();
+    runAdb(selector() << _("shell") << _("am") << _("force-stop") << m_androidRunnable.packageName,
+           nullptr, 30);
 
     // try killing it via kill -9
     const QByteArray out = runPs();
@@ -334,34 +334,22 @@ void AndroidRunner::asyncStart()
 {
     QMutexLocker locker(&m_mutex);
     forceStop();
+    QString errorMessage;
 
-    if (m_useCppDebugger) {
-        // Remove pong file.
-        QProcess adb;
-        adb.start(m_adb, selector() << _("shell") << _("rm") << m_pongFile);
-        adb.waitForFinished();
-    }
+    if (m_useCppDebugger)
+        runAdb(selector() << _("shell") << _("rm") << m_pongFile); // Remove pong file.
 
-    foreach (const QStringList &entry, m_androidRunnable.beforeStartADBCommands) {
-        QProcess adb;
-        adb.start(m_adb, selector() << entry);
-        adb.waitForFinished();
-    }
+    foreach (const QStringList &entry, m_androidRunnable.beforeStartADBCommands)
+        runAdb(selector() << entry);
 
     QStringList args = selector();
     args << _("shell") << _("am") << _("start") << _("-n") << m_androidRunnable.intentName;
 
     if (m_useCppDebugger) {
-        QProcess adb;
-        adb.start(m_adb, selector() << _("forward")
-                  << QString::fromLatin1("tcp:%1").arg(m_localGdbServerPort.number())
-                  << _("localfilesystem:") + m_gdbserverSocket);
-        if (!adb.waitForStarted()) {
-            emit remoteProcessFinished(tr("Failed to forward C++ debugging ports. Reason: %1.").arg(adb.errorString()));
-            return;
-        }
-        if (!adb.waitForFinished(10000)) {
-            emit remoteProcessFinished(tr("Failed to forward C++ debugging ports."));
+        if (!runAdb(selector() << _("forward")
+                    << QString::fromLatin1("tcp:%1").arg(m_localGdbServerPort.number())
+                    << _("localfilesystem:") + m_gdbserverSocket, &errorMessage)) {
+            emit remoteProcessFinished(tr("Failed to forward C++ debugging ports. Reason: %1.").arg(errorMessage));
             return;
         }
 
@@ -380,15 +368,9 @@ void AndroidRunner::asyncStart()
         args << _("-e") << _("gdbserver_socket") << m_gdbserverSocket;
 
         if (m_handShakeMethod == SocketHandShake) {
-            QProcess adb;
             const QString port = QString::fromLatin1("tcp:%1").arg(socketHandShakePort);
-            adb.start(m_adb, selector() << _("forward") << port << _("localabstract:") + pingPongSocket);
-            if (!adb.waitForStarted()) {
-                emit remoteProcessFinished(tr("Failed to forward ping pong ports. Reason: %1.").arg(adb.errorString()));
-                return;
-            }
-            if (!adb.waitForFinished()) {
-                emit remoteProcessFinished(tr("Failed to forward ping pong ports."));
+            if (!runAdb(selector() << _("forward") << port << _("localabstract:") + pingPongSocket, &errorMessage)) {
+                emit remoteProcessFinished(tr("Failed to forward ping pong ports. Reason: %1.").arg(errorMessage));
                 return;
             }
         }
@@ -397,14 +379,8 @@ void AndroidRunner::asyncStart()
     if (m_qmlDebugServices != QmlDebug::NoQmlDebugServices) {
         // currently forward to same port on device and host
         const QString port = QString::fromLatin1("tcp:%1").arg(m_qmlPort.number());
-        QProcess adb;
-        adb.start(m_adb, selector() << _("forward") << port << port);
-        if (!adb.waitForStarted()) {
-            emit remoteProcessFinished(tr("Failed to forward QML debugging ports. Reason: %1.").arg(adb.errorString()));
-            return;
-        }
-        if (!adb.waitForFinished()) {
-            emit remoteProcessFinished(tr("Failed to forward QML debugging ports."));
+        if (!runAdb(selector() << _("forward") << port << port, &errorMessage)) {
+            emit remoteProcessFinished(tr("Failed to forward QML debugging ports. Reason: %1.").arg(errorMessage));
             return;
         }
 
@@ -414,15 +390,8 @@ void AndroidRunner::asyncStart()
                 .arg(m_qmlPort.number()).arg(QmlDebug::qmlDebugServices(m_qmlDebugServices));
     }
 
-    QProcess adb;
-    adb.start(m_adb, args);
-    if (!adb.waitForStarted()) {
-        emit remoteProcessFinished(tr("Failed to start the activity. Reason: %1.").arg(adb.errorString()));
-        return;
-    }
-    if (!adb.waitForFinished(10000)) {
-        adb.terminate();
-        emit remoteProcessFinished(tr("Unable to start \"%1\".").arg(m_androidRunnable.packageName));
+    if (!runAdb(args, &errorMessage)) {
+        emit remoteProcessFinished(tr("Failed to start the activity. Reason: %1.").arg(errorMessage));
         return;
     }
 
@@ -476,9 +445,7 @@ void AndroidRunner::asyncStart()
                 tmp.open();
                 tmp.close();
 
-                QProcess process;
-                process.start(m_adb, selector() << _("pull") << m_pingFile << tmp.fileName());
-                process.waitForFinished();
+                runAdb(selector() << _("pull") << m_pingFile << tmp.fileName());
 
                 QFile res(tmp.fileName());
                 const bool doBreak = res.size();
@@ -510,18 +477,28 @@ bool AndroidRunner::adbShellAmNeedsQuotes()
     // The command will fail with a complaint about the "--dummy"
     // option on newer SDKs, and with "No intent supplied" on older ones.
     // In case the test itself fails assume a new SDK.
-    QProcess adb;
-    adb.start(m_adb, selector() << _("shell") << _("am") << _("start")
-                                << _("-e") << _("dummy") <<_("dummy --dummy"));
-    if (!adb.waitForStarted())
+    Utils::SynchronousProcess adb;
+    adb.setTimeoutS(10);
+    Utils::SynchronousProcessResponse response
+            = adb.run(m_adb, selector() << _("shell") << _("am") << _("start")
+                      << _("-e") << _("dummy") <<_("dummy --dummy"));
+    if (response.result == Utils::SynchronousProcessResponse::StartFailed
+            || response.result != Utils::SynchronousProcessResponse::Finished)
         return true;
 
-    if (!adb.waitForFinished(10000))
-        return true;
+    const QString output = response.allOutput();
+    return output.contains(QLatin1String("Error: No intent supplied"));
+}
 
-    QByteArray output = adb.readAllStandardError() + adb.readAllStandardOutput();
-    bool oldSdk = output.contains("Error: No intent supplied");
-    return !oldSdk;
+bool AndroidRunner::runAdb(const QStringList &args, QString *errorMessage, int timeoutS)
+{
+    Utils::SynchronousProcess adb;
+    adb.setTimeoutS(timeoutS);
+    Utils::SynchronousProcessResponse response
+            = adb.run(m_adb, args);
+    if (errorMessage)
+        *errorMessage = response.exitMessage(m_adb, timeoutS);
+    return response.result == Utils::SynchronousProcessResponse::Finished;
 }
 
 void AndroidRunner::handleRemoteDebuggerRunning()
@@ -535,9 +512,7 @@ void AndroidRunner::handleRemoteDebuggerRunning()
             QTemporaryFile tmp(QDir::tempPath() + _("/pingpong"));
             tmp.open();
 
-            QProcess process;
-            process.start(m_adb, selector() << _("push") << tmp.fileName() << m_pongFile);
-            process.waitForFinished();
+            runAdb(selector() << _("push") << tmp.fileName() << m_pongFile);
         }
         QTC_CHECK(m_processPID != -1);
     }
@@ -558,11 +533,8 @@ void AndroidRunner::stop()
     m_adbLogcatProcess.waitForFinished();
     m_psProc.kill();
     m_psProc.waitForFinished();
-    foreach (const QStringList &entry, m_androidRunnable.afterFinishADBCommands) {
-        QProcess adb;
-        adb.start(m_adb, selector() << entry);
-        adb.waitForFinished();
-    }
+    foreach (const QStringList &entry, m_androidRunnable.afterFinishADBCommands)
+        runAdb(selector() << entry);
 }
 
 void AndroidRunner::logcatProcess(const QByteArray &text, QByteArray &buffer, bool onlyError)
@@ -622,19 +594,9 @@ void AndroidRunner::logcatReadStandardOutput()
 
 void AndroidRunner::adbKill(qint64 pid)
 {
-    {
-        QProcess process;
-        process.start(m_adb, selector() << _("shell")
-            << _("kill") << QLatin1String("-9") << QString::number(pid));
-        process.waitForFinished();
-    }
-    {
-        QProcess process;
-        process.start(m_adb, selector() << _("shell")
-            << _("run-as") << m_androidRunnable.packageName
-            << _("kill") << QLatin1String("-9") << QString::number(pid));
-        process.waitForFinished();
-    }
+    runAdb(selector() << _("shell") << _("kill") << QLatin1String("-9") << QString::number(pid));
+    runAdb(selector() << _("shell") << _("run-as") << m_androidRunnable.packageName
+           << _("kill") << QLatin1String("-9") << QString::number(pid));
 }
 
 QString AndroidRunner::displayName() const
diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h
index fb3c9edf177bef286b6d762c445b278d291a4a92..b2e09e64cfce0ec4da5989f57a23ef117676eacf 100644
--- a/src/plugins/android/androidrunner.h
+++ b/src/plugins/android/androidrunner.h
@@ -90,6 +90,7 @@ private:
     bool adbShellAmNeedsQuotes();
 
 private:
+    bool runAdb(const QStringList &args, QString *errorMessage = nullptr, int timeoutS = 10);
     QProcess m_adbLogcatProcess;
     QProcess m_psProc;
     QTimer m_checkPIDTimer;
diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
index c3293afbb8b8724c9bcf3ecb8530009cbec13122..ea7ea11431886d90db8fe57d21220b465b2a1a31 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
+++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
@@ -32,11 +32,11 @@
 #include <coreplugin/icore.h>
 
 #include <utils/runextensions.h>
+#include <utils/synchronousprocess.h>
 
 #include <QDateTime>
 #include <QFile>
 #include <QFileInfo>
-#include <QProcess>
 #include <QXmlStreamWriter>
 
 namespace Beautifier {
@@ -78,18 +78,17 @@ static int parseVersion(const QString &text)
 
 static int updateVersionHelper(const QString &command)
 {
-    QProcess process;
-    process.start(command, {"--version"});
-    if (!process.waitForFinished()) {
-        process.kill();
+    Utils::SynchronousProcess process;
+    Utils::SynchronousProcessResponse response
+            = process.run(command, QStringList() << QLatin1String("--version"));
+    if (response.result != Utils::SynchronousProcessResponse::Finished)
         return 0;
-    }
 
     // Astyle prints the version on stdout or stderr, depending on platform
-    const int version = parseVersion(QString::fromUtf8(process.readAllStandardOutput()).trimmed());
+    const int version = parseVersion(response.stdOut.trimmed());
     if (version != 0)
         return version;
-    return parseVersion(QString::fromUtf8(process.readAllStandardError()).trimmed());
+    return parseVersion(response.stdErr.trimmed());
 }
 
 void ArtisticStyleSettings::updateVersion()
@@ -155,10 +154,11 @@ QString ArtisticStyleSettings::documentationFilePath() const
 
 void ArtisticStyleSettings::createDocumentationFile() const
 {
-    QProcess process;
-    process.start(command(), {"-h"});
-    process.waitForFinished(2000); // show help should be really fast.
-    if (process.error() != QProcess::UnknownError)
+    Utils::SynchronousProcess process;
+    process.setTimeoutS(2);
+    Utils::SynchronousProcessResponse response
+            = process.run(command(), QStringList() << QLatin1String("-h"));
+    if (response.result != Utils::SynchronousProcessResponse::Finished)
         return;
 
     QFile file(documentationFilePath());
@@ -176,8 +176,7 @@ void ArtisticStyleSettings::createDocumentationFile() const
     stream.writeStartElement(Constants::DOCUMENTATION_XMLROOT);
 
     // astyle writes its output to 'error'...
-    const QStringList lines = QString::fromUtf8(process.readAllStandardError())
-            .split('\n');
+    const QStringList lines = response.stdErr.split(QLatin1Char('\n'));
     QStringList keys;
     QStringList docu;
     for (QString line : lines) {
diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp
index 508a5117422ec14c5241ed0ad0df37bf4d815671..c44c2e2b55dfb34d68c778dc1f2770bea64504f0 100644
--- a/src/plugins/beautifier/beautifierplugin.cpp
+++ b/src/plugins/beautifier/beautifierplugin.cpp
@@ -45,6 +45,7 @@
 #include <texteditor/texteditor.h>
 #include <utils/qtcassert.h>
 #include <utils/runextensions.h>
+#include <utils/synchronousprocess.h>
 
 #include <QDir>
 #include <QFileInfo>
@@ -84,20 +85,18 @@ FormatTask format(FormatTask task)
         }
 
         // Format temporary file
-        QProcess process;
         QStringList options = task.command.options();
-        options.replaceInStrings("%file", sourceFile.fileName());
-        process.start(executable, options);
-        if (!process.waitForFinished(5000)) {
-            process.kill();
-            task.error = BeautifierPlugin::tr("Cannot call %1 or some other error occurred. Timeout "
-                                     "reached while formatting file %2.")
-                    .arg(executable).arg(task.filePath);
+        options.replaceInStrings(QLatin1String("%file"), sourceFile.fileName());
+        Utils::SynchronousProcess process;
+        process.setTimeoutS(5);
+        Utils::SynchronousProcessResponse response = process.run(executable, options);
+        if (response.result != Utils::SynchronousProcessResponse::Finished) {
+            task.error = QObject::tr("Failed to format: %1.").arg(response.exitMessage(executable, 5));
             return task;
         }
-        const QByteArray output = process.readAllStandardError();
+        const QString output = response.stdErr;
         if (!output.isEmpty())
-            task.error = executable + ": " + QString::fromUtf8(output);
+            task.error = executable + QLatin1String(": ") + output;
 
         // Read text back
         Utils::FileReader reader;
@@ -107,8 +106,8 @@ FormatTask format(FormatTask task)
             return task;
         }
         task.formattedData = QString::fromUtf8(reader.data());
-        return task;
     }
+    return task;
 
     case Command::PipeProcessing: {
         QProcess process;
@@ -123,7 +122,7 @@ FormatTask format(FormatTask task)
         }
         process.write(task.sourceData.toUtf8());
         process.closeWriteChannel();
-        if (!process.waitForFinished(5000)) {
+        if (!process.waitForFinished(5000) && process.state() == QProcess::Running) {
             process.kill();
             task.error = BeautifierPlugin::tr("Cannot call %1 or some other error occurred. Timeout "
                                      "reached while formatting file %2.")
diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
index ed552ae7208ecb5401702d80b96719baf88f614f..bdbb34c21175f3700fea6b85d3f7d2a7c9746126 100644
--- a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
+++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
@@ -31,6 +31,8 @@
 
 #include <coreplugin/icore.h>
 
+#include <utils/synchronousprocess.h>
+
 #include <QDateTime>
 #include <QFile>
 #include <QFileInfo>
@@ -124,10 +126,11 @@ QString UncrustifySettings::documentationFilePath() const
 
 void UncrustifySettings::createDocumentationFile() const
 {
-    QProcess process;
-    process.start(command(), {"--show-config"});
-    process.waitForFinished(2000); // show config should be really fast.
-    if (process.error() != QProcess::UnknownError)
+    Utils::SynchronousProcess process;
+    process.setTimeoutS(2);
+    Utils::SynchronousProcessResponse response
+            = process.run(command(), QStringList() << QLatin1String("--show-config"));
+    if (response.result != Utils::SynchronousProcessResponse::Finished)
         return;
 
     QFile file(documentationFilePath());
@@ -144,7 +147,7 @@ void UncrustifySettings::createDocumentationFile() const
     stream.writeComment("Created " + QDateTime::currentDateTime().toString(Qt::ISODate));
     stream.writeStartElement(Constants::DOCUMENTATION_XMLROOT);
 
-    const QStringList lines = QString::fromUtf8(process.readAll()).split('\n');
+    const QStringList lines = response.allOutput().split(QLatin1Char('\n'));
     const int totalLines = lines.count();
     for (int i = 0; i < totalLines; ++i) {
         const QString &line = lines.at(i);
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index c29e6e13ab8692b1b6b4213a54b9f3088347bb67..a9b989049300f7b45a51ca7a500023611b4b5fc6 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -2159,14 +2159,14 @@ QString ClearCasePlugin::runExtDiff(const QString &workingDir, const QStringList
     QStringList args(m_settings.diffArgs.split(QLatin1Char(' '), QString::SkipEmptyParts));
     args << arguments;
 
-    QProcess process;
+    SynchronousProcess process;
+    process.setTimeoutS(timeOutS);
     process.setWorkingDirectory(workingDir);
-    process.start(executable, args);
-    if (!process.waitForFinished(timeOutS * 1000))
+    process.setCodec(outputCodec ? outputCodec : QTextCodec::codecForName("UTF-8"));
+    SynchronousProcessResponse response = process.run(executable, args);
+    if (response.result != SynchronousProcessResponse::Finished)
         return QString();
-    QByteArray ba = process.readAll();
-    return outputCodec ? outputCodec->toUnicode(ba) :
-                         QString::fromLocal8Bit(ba.constData(), ba.size());
+    return response.allOutput();
 }
 
 void ClearCasePlugin::syncSlot()
diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp
index 98c36953426d32a61370afe085f9b7118f5fed69..87f3c07a931c5dc9df175799a6318814f7ca8000 100644
--- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp
+++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp
@@ -280,7 +280,7 @@ void BuildDirManager::stopProcess()
 
     if (m_cmakeProcess->state() == QProcess::Running) {
         m_cmakeProcess->terminate();
-        if (!m_cmakeProcess->waitForFinished(500))
+        if (!m_cmakeProcess->waitForFinished(500) && m_cmakeProcess->state() == QProcess::Running)
             m_cmakeProcess->kill();
     }
 
@@ -305,9 +305,10 @@ void BuildDirManager::cleanUpProcess()
 
     if (m_cmakeProcess->state() == QProcess::Running) {
         m_cmakeProcess->terminate();
-        if (!m_cmakeProcess->waitForFinished(500))
+        if (!m_cmakeProcess->waitForFinished(500) && m_cmakeProcess->state() == QProcess::Running)
             m_cmakeProcess->kill();
     }
+    m_cmakeProcess->waitForFinished();
     delete m_cmakeProcess;
     m_cmakeProcess = nullptr;
 
diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp
index ec6ac3d79957d5ace39f021831dca8a222b8c769..986a9cb30fc0edf67301ce1008dba55da50e683c 100644
--- a/src/plugins/debugger/debuggeritem.cpp
+++ b/src/plugins/debugger/debuggeritem.cpp
@@ -35,6 +35,7 @@
 #include <utils/hostosinfo.h>
 #include <utils/macroexpander.h>
 #include <utils/qtcassert.h>
+#include <utils/synchronousprocess.h>
 
 #include <QFileInfo>
 #include <QProcess>
@@ -117,66 +118,66 @@ void DebuggerItem::reinitializeFromFile()
     if (fileInfo.baseName().toLower().contains(QLatin1String("lldb-mi")))
         version = "--version";
 
-    QProcess proc;
-    proc.start(m_command.toString(), QStringList({ QLatin1String(version) }));
-    if (!proc.waitForStarted() || !proc.waitForFinished()) {
+    SynchronousProcess proc;
+    SynchronousProcessResponse response
+            = proc.run(m_command.toString(), QStringList({ QLatin1String(version) }));
+    if (response.result != SynchronousProcessResponse::Finished) {
         m_engineType = NoEngineType;
         return;
     }
     m_abis.clear();
-    QByteArray ba = proc.readAll();
-    if (ba.contains("gdb")) {
+    const QString output = response.allOutput();
+    if (output.contains("gdb")) {
         m_engineType = GdbEngineType;
         const char needle[] = "This GDB was configured as \"";
         // E.g.  "--host=i686-pc-linux-gnu --target=arm-unknown-nto-qnx6.5.0".
         // or "i686-linux-gnu"
-        int pos1 = ba.indexOf(needle);
+        int pos1 = output.indexOf(needle);
         if (pos1 != -1) {
             pos1 += int(strlen(needle));
-            int pos2 = ba.indexOf('"', pos1 + 1);
-            QByteArray target = ba.mid(pos1, pos2 - pos1);
+            int pos2 = output.indexOf('"', pos1 + 1);
+            QString target = output.mid(pos1, pos2 - pos1);
             int pos3 = target.indexOf("--target=");
             if (pos3 >= 0)
                 target = target.mid(pos3 + 9);
-            m_abis.append(Abi::abiFromTargetTriplet(QString::fromLatin1(target)));
+            m_abis.append(Abi::abiFromTargetTriplet(target));
         } else {
             // Fallback.
             m_abis = Abi::abisOfBinary(m_command); // FIXME: Wrong.
         }
 
         // Version
-        QString all = QString::fromUtf8(ba);
         bool isMacGdb, isQnxGdb;
         int version = 0, buildVersion = 0;
-        Debugger::Internal::extractGdbVersion(all,
+        Debugger::Internal::extractGdbVersion(output,
             &version, &buildVersion, &isMacGdb, &isQnxGdb);
         if (version)
             m_version = QString::fromLatin1("%1.%2.%3")
                 .arg(version / 10000).arg((version / 100) % 100).arg(version % 100);
         return;
     }
-    if (ba.startsWith("lldb") || ba.startsWith("LLDB")) {
+    if (output.startsWith("lldb") || output.startsWith("LLDB")) {
         m_engineType = LldbEngineType;
         m_abis = Abi::abisOfBinary(m_command);
 
         // Version
-        if (ba.startsWith(("lldb version "))) { // Linux typically.
+        if (output.startsWith(("lldb version "))) { // Linux typically.
             int pos1 = int(strlen("lldb version "));
-            int pos2 = ba.indexOf(' ', pos1);
-            m_version = QString::fromLatin1(ba.mid(pos1, pos2 - pos1));
-        } else if (ba.startsWith("lldb-") || ba.startsWith("LLDB-")) { // Mac typically.
-            m_version = QString::fromLatin1(ba.mid(5));
+            int pos2 = output.indexOf(' ', pos1);
+            m_version = output.mid(pos1, pos2 - pos1);
+        } else if (output.startsWith("lldb-") || output.startsWith("LLDB-")) { // Mac typically.
+            m_version = output.mid(5);
         }
         return;
     }
-    if (ba.startsWith("cdb")) {
+    if (output.startsWith("cdb")) {
         // "cdb version 6.2.9200.16384"
         m_engineType = CdbEngineType;
         m_abis = Abi::abisOfBinary(m_command);
-        m_version = QString::fromLatin1(ba).section(QLatin1Char(' '), 2);
+        m_version = output.section(QLatin1Char(' '), 2);
         return;
     }
-    if (ba.startsWith("Python")) {
+    if (output.startsWith("Python")) {
         m_engineType = PdbEngineType;
         return;
     }
diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp
index e5716e4a15f03fcc7b949c80b16e6f58fbc5f99a..c02a87f9c24297424dde302a80a9f65153c8cf07 100644
--- a/src/plugins/debugger/debuggeritemmanager.cpp
+++ b/src/plugins/debugger/debuggeritemmanager.cpp
@@ -33,12 +33,12 @@
 #include <utils/fileutils.h>
 #include <utils/persistentsettings.h>
 #include <utils/qtcassert.h>
+#include <utils/synchronousprocess.h>
 #include <utils/hostosinfo.h>
 
 #include <QDebug>
 #include <QDir>
 #include <QFileInfo>
-#include <QProcess>
 
 using namespace Core;
 using namespace ProjectExplorer;
@@ -225,17 +225,18 @@ void DebuggerItemManager::autoDetectGdbOrLldbDebuggers()
     FileNameList suspects;
 
     if (HostOsInfo::isMacHost()) {
-        QProcess lldbInfo;
-        lldbInfo.start(QLatin1String("xcrun"), QStringList() << QLatin1String("--find")
-                       << QLatin1String("lldb"));
-        if (!lldbInfo.waitForFinished(2000)) {
-            lldbInfo.kill();
-            lldbInfo.waitForFinished();
-        } else {
-            QByteArray lPath = lldbInfo.readAll();
-            const QFileInfo fi(QString::fromLocal8Bit(lPath.data(), lPath.size() -1));
-            if (fi.exists() && fi.isExecutable() && !fi.isDir())
-                suspects.append(FileName::fromString(fi.absoluteFilePath()));
+        SynchronousProcess lldbInfo;
+        lldbInfo.setTimeoutS(2);
+        SynchronousProcessResponse response
+                = lldbInfo.run(QLatin1String("xcrun"), QStringList() << QLatin1String("--find")
+                               << QLatin1String("lldb"));
+        if (response.result == Utils::SynchronousProcessResponse::Finished) {
+            QString lPath = response.allOutput();
+            if (!lPath.isEmpty()) {
+                const QFileInfo fi(lPath);
+                if (fi.exists() && fi.isExecutable() && !fi.isDir())
+                    suspects.append(FileName::fromString(fi.absoluteFilePath()));
+            }
         }
     }
 
diff --git a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
index 4769eecf3a3dc30b348a2b76280cef182197899b..11319c47c97509ffcf4e92d3e5fb04e7395d9820 100644
--- a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
+++ b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
@@ -415,7 +415,7 @@ static QString findQtInstallPath(const FileName &qmakePath)
         return QString();
     }
     proc.closeWriteChannel();
-    if (!proc.waitForFinished()) {
+    if (!proc.waitForFinished() && proc.state() == QProcess::Running) {
         SynchronousProcess::stopProcess(proc);
         qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(qmakePath.toString()));
         return QString();
diff --git a/src/plugins/debugger/gdb/coregdbadapter.cpp b/src/plugins/debugger/gdb/coregdbadapter.cpp
index d946efbe4ae696d82d80b1e7d285b34b033469fe..109592bd6205dbbc90091cefcf8d9faa8afa7f23 100644
--- a/src/plugins/debugger/gdb/coregdbadapter.cpp
+++ b/src/plugins/debugger/gdb/coregdbadapter.cpp
@@ -34,6 +34,7 @@
 
 #include <utils/fileutils.h>
 #include <utils/qtcassert.h>
+#include <utils/synchronousprocess.h>
 
 #include <QDir>
 #include <QTemporaryFile>
@@ -135,23 +136,23 @@ GdbCoreEngine::readExecutableNameFromCore(const QString &debuggerCommand, const
     args.append(QLatin1String("-c"));
     args.append(coreFile);
 
-    QProcess proc;
+    SynchronousProcess proc;
     QStringList envLang = QProcess::systemEnvironment();
     Utils::Environment::setupEnglishOutput(&envLang);
     proc.setEnvironment(envLang);
-    proc.start(debuggerCommand, args);
+    SynchronousProcessResponse response = proc.run(debuggerCommand, args);
 
-    if (proc.waitForFinished()) {
-        QByteArray ba = proc.readAllStandardOutput();
+    if (response.result == SynchronousProcessResponse::Finished) {
+        QString output = response.stdOut;
         // Core was generated by `/data/dev/creator-2.6/bin/qtcreator'.
         // Program terminated with signal 11, Segmentation fault.
-        int pos1 = ba.indexOf("Core was generated by");
+        int pos1 = output.indexOf("Core was generated by");
         if (pos1 != -1) {
             pos1 += 23;
-            int pos2 = ba.indexOf('\'', pos1);
+            int pos2 = output.indexOf('\'', pos1);
             if (pos2 != -1) {
                 cinfo.isCore = true;
-                cinfo.rawStringFromCore = QString::fromLocal8Bit(ba.mid(pos1, pos2 - pos1));
+                cinfo.rawStringFromCore = output.mid(pos1, pos2 - pos1);
                 cinfo.foundExecutableName = findExecutableFromName(cinfo.rawStringFromCore, coreFile);
             }
         }
diff --git a/src/plugins/ios/iosprobe.cpp b/src/plugins/ios/iosprobe.cpp
index 72069fb91b14300223774a86fdec01b1918a4e37..47c4e2c7a7da071379d6e8be1b6a38fdfba49a5e 100644
--- a/src/plugins/ios/iosprobe.cpp
+++ b/src/plugins/ios/iosprobe.cpp
@@ -25,6 +25,8 @@
 
 #include "iosprobe.h"
 
+#include <utils/synchronousprocess.h>
+
 #include <QDir>
 #include <QFileInfo>
 #include <QFileInfoList>
@@ -93,14 +95,16 @@ void IosProbe::addDeveloperPath(const QString &path)
 
 void IosProbe::detectDeveloperPaths()
 {
-    QProcess selectedXcode;
     QString program = QLatin1String("/usr/bin/xcode-select");
     QStringList arguments(QLatin1String("--print-path"));
-    selectedXcode.start(program, arguments, QProcess::ReadOnly);
-    if (!selectedXcode.waitForFinished() || selectedXcode.exitCode()) {
+
+    Utils::SynchronousProcess selectedXcode;
+    selectedXcode.setTimeoutS(5);
+    Utils::SynchronousProcessResponse response = selectedXcode.run(program, arguments);
+    if (response.result != Utils::SynchronousProcessResponse::Finished) {
         qCWarning(probeLog) << QString::fromLatin1("Could not detect selected xcode with /usr/bin/xcode-select");
     } else {
-        QString path = QString::fromLocal8Bit(selectedXcode.readAllStandardOutput());
+        QString path = response.stdOut;
         path.chop(1);
         addDeveloperPath(path);
     }
diff --git a/src/plugins/ios/iossimulator.cpp b/src/plugins/ios/iossimulator.cpp
index 9494b356bc9b40ec7a2bcc84243fbaae7eea8499..a5c0bf3965837c53cadf709603690f95a93b92d4 100644
--- a/src/plugins/ios/iossimulator.cpp
+++ b/src/plugins/ios/iossimulator.cpp
@@ -187,7 +187,7 @@ Utils::Port IosSimulator::nextPort() const
         if (!portVerifier.waitForStarted())
             break;
         portVerifier.closeWriteChannel();
-        if (!portVerifier.waitForFinished())
+        if (!portVerifier.waitForFinished() && portVerifier.state() == QProcess::Running)
             break;
         if (portVerifier.exitStatus() != QProcess::NormalExit
                 || portVerifier.exitCode() != 0)
diff --git a/src/plugins/perforce/perforcechecker.cpp b/src/plugins/perforce/perforcechecker.cpp
index 7c8c27e780d7651237554bcc7cf2f76e84530b96..b7f5f56ccb5b9d073434e39b4c86852140a536cd 100644
--- a/src/plugins/perforce/perforcechecker.cpp
+++ b/src/plugins/perforce/perforcechecker.cpp
@@ -59,9 +59,9 @@ bool PerforceChecker::isRunning() const
     return m_process.state() == QProcess::Running;
 }
 
-bool PerforceChecker::waitForFinished(int msec)
+bool PerforceChecker::waitForFinished()
 {
-    return m_process.waitForFinished(msec);
+    return m_process.waitForFinished() || m_process.state() == QProcess::NotRunning;
 }
 
 void PerforceChecker::resetOverrideCursor()
diff --git a/src/plugins/perforce/perforcechecker.h b/src/plugins/perforce/perforcechecker.h
index b8680959833772e611738b88ea46e27df1a08621..e1a7ec67b6918c21a601f2aacf00dee12776d6be 100644
--- a/src/plugins/perforce/perforcechecker.h
+++ b/src/plugins/perforce/perforcechecker.h
@@ -49,7 +49,7 @@ public:
 
     bool isRunning() const;
 
-    bool waitForFinished(int msec = -1);
+    bool waitForFinished();
 
     bool useOverideCursor() const;
     void setUseOverideCursor(bool v);
diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp
index 0bf126ed3a18ec4347f2bc553a14dc53efb125bc..37beaa309d41ec8dd08df78ec71488a15d2e9b29 100644
--- a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp
+++ b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp
@@ -238,7 +238,7 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env,
                                                         const QString &batchArgs,
                                                         QMap<QString, QString> &envPairs)
 {
-    const QByteArray marker = "####################\r\n";
+    const QString marker = "####################\r\n";
     // Create a temporary file name for the output. Use a temporary file here
     // as I don't know another way to do this in Qt...
     // Note, can't just use a QTemporaryFile all the way through as it remains open
@@ -254,47 +254,39 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env,
         call += batchArgs.toLocal8Bit();
     }
     saver.write(call + "\r\n");
-    saver.write("@echo " + marker);
+    saver.write("@echo " + marker.toLocal8Bit());
     saver.write("set\r\n");
-    saver.write("@echo " + marker);
+    saver.write("@echo " + marker.toLocal8Bit());
     if (!saver.finalize()) {
         qWarning("%s: %s", Q_FUNC_INFO, qPrintable(saver.errorString()));
         return false;
     }
 
-    Utils::QtcProcess run;
+    Utils::SynchronousProcess run;
     // As of WinSDK 7.1, there is logic preventing the path from being set
     // correctly if "ORIGINALPATH" is already set. That can cause problems
     // if Creator is launched within a session set up by setenv.cmd.
     env.unset(QLatin1String("ORIGINALPATH"));
-    run.setEnvironment(env);
+    run.setEnvironment(env.toStringList());
+    run.setTimeoutS(10);
     Utils::FileName cmdPath = Utils::FileName::fromUserInput(QString::fromLocal8Bit(qgetenv("COMSPEC")));
     if (cmdPath.isEmpty())
         cmdPath = env.searchInPath(QLatin1String("cmd.exe"));
     // Windows SDK setup scripts require command line switches for environment expansion.
-    QString cmdArguments = QLatin1String(" /E:ON /V:ON /c \"");
-    cmdArguments += QDir::toNativeSeparators(saver.fileName());
-    cmdArguments += QLatin1Char('"');
-    run.setCommand(cmdPath.toString(), cmdArguments);
+    QStringList cmdArguments;
+    cmdArguments << QLatin1String("/E:ON") << QLatin1String("/V:ON") <<  QLatin1String("/c");
+    cmdArguments << QDir::toNativeSeparators(saver.fileName());
     if (debug)
-        qDebug() << "readEnvironmentSetting: " << call << cmdPath << cmdArguments
+        qDebug() << "readEnvironmentSetting: " << call << cmdPath << cmdArguments.join(' ')
                  << " Env: " << env.size();
-    run.start();
-
-    if (!run.waitForStarted()) {
-        qWarning("%s: Unable to run '%s': %s", Q_FUNC_INFO, qPrintable(batchFile),
-                 qPrintable(run.errorString()));
-        return false;
-    }
-    if (!run.waitForFinished()) {
-        qWarning("%s: Timeout running '%s'", Q_FUNC_INFO, qPrintable(batchFile));
-        Utils::SynchronousProcess::stopProcess(run);
+    Utils::SynchronousProcessResponse response = run.run(cmdPath.toString(), cmdArguments);
+    if (response.result != Utils::SynchronousProcessResponse::Finished) {
+        qWarning() << response.exitMessage(cmdPath.toString(), 10);
         return false;
     }
+
     // The SDK/MSVC scripts do not return exit codes != 0. Check on stdout.
-    QByteArray stdOut = run.readAllStandardOutput();
-    if (!stdOut.isEmpty() && (stdOut.contains("Unknown") || stdOut.contains("Error")))
-        qWarning("%s: '%s' reports:\n%s", Q_FUNC_INFO, call.constData(), stdOut.constData());
+    const QString stdOut = response.stdOut;
 
     //
     // Now parse the file to get the environment settings
@@ -304,17 +296,15 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env,
         return false;
     }
 
-    stdOut = stdOut.mid(start + marker.size());
-
-    int end = stdOut.indexOf(marker);
+    int end = stdOut.indexOf(marker, start + 1);
     if (end == -1) {
         qWarning("Could not find end marker in stdout output.");
         return false;
     }
 
-    stdOut = stdOut.left(end);
+    const QString output = stdOut.mid(start, end - start);
 
-    QStringList lines = QString::fromLocal8Bit(stdOut).split(QLatin1String("\r\n"));
+    QStringList lines = output.split(QLatin1String("\r\n"));
     QRegExp regexp(QLatin1String("(\\w*)=(.*)"));
     foreach (const QString &line, lines) {
         if (regexp.exactMatch(line)) {
diff --git a/src/plugins/projectexplorer/applicationlauncher.cpp b/src/plugins/projectexplorer/applicationlauncher.cpp
index e397454803c8b095ad2b12a056394891a468150f..4c14e9a5bb34805f6565f38d02ae226f504529b2 100644
--- a/src/plugins/projectexplorer/applicationlauncher.cpp
+++ b/src/plugins/projectexplorer/applicationlauncher.cpp
@@ -174,7 +174,7 @@ void ApplicationLauncher::stop()
         return;
     if (d->m_currentMode == Gui) {
         d->m_guiProcess.terminate();
-        if (!d->m_guiProcess.waitForFinished(1000)) { // This is blocking, so be fast.
+        if (!d->m_guiProcess.waitForFinished(1000) && d->m_guiProcess.state() == QProcess::Running) { // This is blocking, so be fast.
             d->m_guiProcess.kill();
             d->m_guiProcess.waitForFinished();
         }
diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
index fa1e83cdabc0377aa7c443c43330a479e69fb5a5..59487384c1c9580c17c0042d8e2c0d8340be098e 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
@@ -28,8 +28,8 @@
 #include "customwizardparameters.h"
 
 #include <utils/hostosinfo.h>
+#include <utils/synchronousprocess.h>
 
-#include <QProcess>
 #include <QDir>
 #include <QFileInfo>
 #include <QDebug>
@@ -83,7 +83,7 @@ static bool
                               const QMap<QString, QString> &fieldMap,
                               QString *stdOut /* = 0 */, QString *errorMessage)
 {
-    QProcess process;
+    Utils::SynchronousProcess process;
     const QString binary = script.front();
     QStringList arguments;
     const int binarySize = script.size();
@@ -107,32 +107,23 @@ static bool
             arguments.push_back(value);
     }
     process.setWorkingDirectory(workingDirectory);
+    process.setTimeoutS(30);
     if (CustomWizard::verbose())
         qDebug("In %s, running:\n%s\n%s\n", qPrintable(workingDirectory),
                qPrintable(binary),
                qPrintable(arguments.join(QLatin1Char(' '))));
-    process.start(binary, arguments);
-    if (!process.waitForStarted()) {
-        *errorMessage = QString::fromLatin1("Unable to start generator script %1: %2").
-                arg(binary, process.errorString());
-        return false;
-    }
-    if (!process.waitForFinished()) {
-        *errorMessage = QString::fromLatin1("Generator script %1 timed out").arg(binary);
-        return false;
-    }
-    if (process.exitStatus() != QProcess::NormalExit) {
-        *errorMessage = QString::fromLatin1("Generator script %1 crashed").arg(binary);
-        return false;
-    }
-    if (process.exitCode() != 0) {
-        const QString stdErr = QString::fromLocal8Bit(process.readAllStandardError());
-        *errorMessage = QString::fromLatin1("Generator script %1 returned %2 (%3)").
-                arg(binary).arg(process.exitCode()).arg(stdErr);
+    Utils::SynchronousProcessResponse response = process.run(binary, arguments);
+    if (response.result != Utils::SynchronousProcessResponse::Finished) {
+        *errorMessage = QString::fromLatin1("Generator script failed: %1")
+                .arg(response.exitMessage(binary, 30));
+        if (!response.stdErr.isEmpty()) {
+            errorMessage->append(QLatin1Char('\n'));
+            errorMessage->append(response.stdErr);
+        }
         return false;
     }
     if (stdOut) {
-        *stdOut = QString::fromLocal8Bit(process.readAllStandardOutput());
+        *stdOut = response.stdOut;
         stdOut->remove(QLatin1Char('\r'));
         if (CustomWizard::verbose())
             qDebug("Output: '%s'\n", qPrintable(*stdOut));
diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp
index 77f9961e2a3c4f2d10f532719506c0f71217aac5..05c6535ec698db866c0e2d38b463e14284b91d84 100644
--- a/src/plugins/projectexplorer/extracompiler.cpp
+++ b/src/plugins/projectexplorer/extracompiler.cpp
@@ -463,7 +463,7 @@ void ProcessExtraCompiler::runInThread(
     if (!isCanceled) {
         handleProcessStarted(&process, sourceContents);
         forever {
-            bool done = process.waitForFinished(200);
+            bool done = process.waitForFinished(200) || process.state() == QProcess::NotRunning;
             isCanceled = futureInterface.isCanceled();
             if (done || isCanceled)
                 break;
@@ -473,7 +473,7 @@ void ProcessExtraCompiler::runInThread(
     isCanceled |= process.state() == QProcess::Running;
     if (isCanceled) {
         process.kill();
-        process.waitForFinished(3000);
+        process.waitForFinished();
         return;
     }
 
diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp
index e657c0dea86d8be4302f95abc509c549c2bf1d6d..627dc67206da12032dde963d328fcc8b4bd625a2 100644
--- a/src/plugins/projectexplorer/gcctoolchain.cpp
+++ b/src/plugins/projectexplorer/gcctoolchain.cpp
@@ -38,11 +38,11 @@
 #include <utils/pathchooser.h>
 #include <utils/qtcassert.h>
 #include <utils/qtcprocess.h>
+#include <utils/synchronousprocess.h>
 
 #include <QBuffer>
 #include <QCoreApplication>
 #include <QFileInfo>
-#include <QProcess>
 #include <QScopedPointer>
 
 #include <QLineEdit>
@@ -70,44 +70,20 @@ static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, cons
     if (gcc.isEmpty() || !gcc.toFileInfo().isExecutable())
         return QByteArray();
 
-    QProcess cpp;
+    SynchronousProcess cpp;
     QStringList environment(env);
     Utils::Environment::setupEnglishOutput(&environment);
 
     cpp.setEnvironment(environment);
-    cpp.start(gcc.toString(), arguments);
-    if (!cpp.waitForStarted()) {
-        qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(gcc.toUserOutput()),
-            qPrintable(cpp.errorString()));
-        return QByteArray();
-    }
-    cpp.closeWriteChannel();
-    if (!cpp.waitForFinished(10000)) {
-        SynchronousProcess::stopProcess(cpp);
-        qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(gcc.toUserOutput()));
-        return QByteArray();
-    }
-    if (cpp.exitStatus() != QProcess::NormalExit) {
-        qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(gcc.toUserOutput()));
+    cpp.setTimeoutS(10);
+    SynchronousProcessResponse response =  cpp.run(gcc.toString(), arguments);
+    if (response.result != SynchronousProcessResponse::Finished ||
+            response.exitCode != 0) {
+        qWarning() << response.exitMessage(gcc.toString(), 10);
         return QByteArray();
     }
 
-    const QByteArray stdErr = SynchronousProcess::normalizeNewlines(
-                QString::fromLocal8Bit(cpp.readAllStandardError())).toLocal8Bit();
-    if (cpp.exitCode() != 0) {
-        qWarning().nospace()
-            << Q_FUNC_INFO << ": " << gcc.toUserOutput() << ' '
-            << arguments.join(QLatin1Char(' ')) << " returned exit code "
-            << cpp.exitCode() << ": " << stdErr;
-        return QByteArray();
-    }
-
-    QByteArray data = SynchronousProcess::normalizeNewlines(
-                QString::fromLocal8Bit(cpp.readAllStandardOutput())).toLocal8Bit();
-    if (!data.isEmpty() && !data.endsWith('\n'))
-        data.append('\n');
-    data.append(stdErr);
-    return data;
+    return response.allOutput().toUtf8();
 }
 
 static const QStringList gccPredefinedMacrosOptions()
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index 310d4f5cce3a002c05e1e676ef959c6931f6c621..1d8df3ac335f8ff85649fd3796c0498dffb5604b 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -237,7 +237,7 @@ QByteArray MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags,
         qWarning("%s: %s", Q_FUNC_INFO, qPrintable(saver.errorString()));
         return predefinedMacros;
     }
-    QProcess cpp;
+    Utils::SynchronousProcess cpp;
     cpp.setEnvironment(env.toStringList());
     cpp.setWorkingDirectory(QDir::tempPath());
     QStringList arguments;
@@ -248,35 +248,23 @@ QByteArray MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags,
     }
 
     arguments << toProcess << QLatin1String("/EP") << QDir::toNativeSeparators(saver.fileName());
-    cpp.start(binary.toString(), arguments);
-    if (!cpp.waitForStarted()) {
-        qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(binary.toUserOutput()),
-            qPrintable(cpp.errorString()));
+    Utils::SynchronousProcessResponse response = cpp.run(binary.toString(), arguments);
+    if (response.result != Utils::SynchronousProcessResponse::Finished ||
+            response.exitCode != 0)
         return predefinedMacros;
-    }
-    cpp.closeWriteChannel();
-    if (!cpp.waitForFinished()) {
-        Utils::SynchronousProcess::stopProcess(cpp);
-        qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(binary.toUserOutput()));
-        return predefinedMacros;
-    }
-    if (cpp.exitStatus() != QProcess::NormalExit) {
-        qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(binary.toUserOutput()));
-        return predefinedMacros;
-    }
 
-    const QList<QByteArray> output = cpp.readAllStandardOutput().split('\n');
-    foreach (const QByteArray& line, output) {
+    const QStringList output = response.stdOut.split('\n');
+    foreach (const QString& line, output) {
         if (line.startsWith('V')) {
-            QList<QByteArray> split = line.split('=');
-            const QByteArray key = split.at(0).mid(1);
-            QByteArray value = split.at(1);
+            QStringList split = line.split('=');
+            const QString key = split.at(0).mid(1);
+            QString value = split.at(1);
             if (!value.isEmpty())
                 value.chop(1); //remove '\n'
             predefinedMacros += "#define ";
-            predefinedMacros += key;
+            predefinedMacros += key.toUtf8();
             predefinedMacros += ' ';
-            predefinedMacros += value;
+            predefinedMacros += value.toUtf8();
             predefinedMacros += '\n';
         }
     }
diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp
index 2c1578b0a6ba7c75a6127256ecd2252dea7531c0..30751883888fcdbb858d58e8db4feac33581a948 100644
--- a/src/plugins/qnx/qnxutils.cpp
+++ b/src/plugins/qnx/qnxutils.cpp
@@ -123,7 +123,7 @@ QList<Utils::EnvironmentItem> QnxUtils::qnxEnvironmentFromEnvFile(const QString
 
     // waiting for finish
     QApplication::setOverrideCursor(Qt::BusyCursor);
-    bool waitResult = process.waitForFinished(10000);
+    bool waitResult = process.waitForFinished(10000) || process.state() == QProcess::NotRunning;
     QApplication::restoreOverrideCursor();
     if (!waitResult) {
         Utils::SynchronousProcess::stopProcess(process);
diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp
index 89eb5f62e1b0337ae008100d645b934c5e7f1008..a12fe364cecfbe17ad4d823361921dd303793da0 100644
--- a/src/plugins/qtsupport/baseqtversion.cpp
+++ b/src/plugins/qtsupport/baseqtversion.cpp
@@ -1392,7 +1392,7 @@ static QByteArray runQmakeQuery(const FileName &binary, const Environment &env,
         *error = QCoreApplication::translate("QtVersion", "Cannot start \"%1\": %2").arg(binary.toUserOutput()).arg(process.errorString());
         return QByteArray();
     }
-    if (!process.waitForFinished(timeOutMS)) {
+    if (!process.waitForFinished(timeOutMS) && process.state() == QProcess::Running) {
         SynchronousProcess::stopProcess(process);
         *error = QCoreApplication::translate("QtVersion", "Timeout running \"%1\" (%2 ms).").arg(binary.toUserOutput()).arg(timeOutMS);
         return QByteArray();
diff --git a/src/plugins/texteditor/generichighlighter/highlightersettings.cpp b/src/plugins/texteditor/generichighlighter/highlightersettings.cpp
index 1231bd41a50c5bd42bfe4c8f59e90c91f81dd9bc..545d04101cf8bfeb47a3e43536059a1c8b92076a 100644
--- a/src/plugins/texteditor/generichighlighter/highlightersettings.cpp
+++ b/src/plugins/texteditor/generichighlighter/highlightersettings.cpp
@@ -27,13 +27,13 @@
 
 #include <coreplugin/icore.h>
 #include <utils/hostosinfo.h>
+#include <utils/synchronousprocess.h>
 
 #include <QSettings>
 #include <QLatin1String>
 #include <QLatin1Char>
 #include <QDir>
 #include <QFile>
-#include <QProcess>
 #include <QStringList>
 
 namespace TextEditor {
@@ -69,11 +69,12 @@ QString findFallbackDefinitionsLocation()
         QStringList programs;
         programs << QLatin1String("kde-config") << QLatin1String("kde4-config");
         foreach (const QString &program, programs) {
-            QProcess process;
-            process.start(program, QStringList(QLatin1String("--prefix")));
-            if (process.waitForStarted(5000)) {
-                process.waitForFinished(5000);
-                QString output = QString::fromLocal8Bit(process.readAllStandardOutput());
+            Utils::SynchronousProcess process;
+            process.setTimeoutS(5);
+            Utils::SynchronousProcessResponse response
+                    = process.run(program, QStringList(QLatin1String("--prefix")));
+            if (response.result == Utils::SynchronousProcessResponse::Finished) {
+                QString output = response.stdOut;
                 output.remove(QLatin1Char('\n'));
                 for (int i = 0; i < kateSyntaxCount; ++i) {
                     dir.setPath(output + kateSyntax[i]);
diff --git a/src/tools/cplusplus-shared/utils.cpp b/src/tools/cplusplus-shared/utils.cpp
index 9e990bfdc790cadb00f30e473b6777eda01ba24a..48178d7cf9e6e282358f5835f5ade79d7a2b9b0f 100644
--- a/src/tools/cplusplus-shared/utils.cpp
+++ b/src/tools/cplusplus-shared/utils.cpp
@@ -66,7 +66,7 @@ void executeCommand(const QString &command, const QStringList &arguments, const
             << endl;
         exit(EXIT_FAILURE);
     }
-    if (!process.waitForFinished()) {
+    if (!process.waitForFinished() && process.state() == QProcess::Running) {
         if (!verbose)
             out << process.readAll() << endl;
         out << QString::fromLatin1("Error: Process \"%1\" did not finish within timeout.")
diff --git a/src/tools/qtcdebugger/main.cpp b/src/tools/qtcdebugger/main.cpp
index 73f781135c67ddf94c98e3393ffab52e687a6e88..a9a68011bcb056714a0b71b251e1895e3a539be3 100644
--- a/src/tools/qtcdebugger/main.cpp
+++ b/src/tools/qtcdebugger/main.cpp
@@ -285,7 +285,7 @@ bool startCreatorAsDebugger(bool asClient, QString *errorMessage)
     // Short execution time: indicates that -client was passed on attach to
     // another running instance of Qt Creator. Keep alive as long as user
     // does not close the process. If that fails, try to launch 2nd instance.
-    const bool waitResult = p.waitForFinished(-1);
+    const bool waitResult = p.waitForFinished(-1) || p.state() == QProcess::NotRunning;
     const bool ranAsClient = asClient && (executionTime.elapsed() < 10000);
     if (waitResult && p.exitStatus() == QProcess::NormalExit && ranAsClient) {
         if (p.exitCode() == 0) {
diff --git a/src/tools/qtpromaker/main.cpp b/src/tools/qtpromaker/main.cpp
index b911c8ae092f339ddf340e3a220c19020f021609..ab257ad4b1183d85256bed1881b12d289f35c374 100644
--- a/src/tools/qtpromaker/main.cpp
+++ b/src/tools/qtpromaker/main.cpp
@@ -206,7 +206,7 @@ void Project::handleBinary(const QString &item)
         qDebug() << "COULD NOT START";
         return;
     }
-    if (!proc.waitForFinished()) {
+    if (!proc.waitForFinished() || proc.state() == QProcess::NotRunning) {
         qDebug() << "COULD NOT FINISH";
         return;
     }