diff options
author | Tobias Hunger <tobias.hunger@qt.io> | 2016-04-29 16:52:58 +0200 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@qt.io> | 2016-05-11 10:04:38 +0000 |
commit | ddefe062c73e35def585f8fc6c90a4f18e47c0f4 (patch) | |
tree | 03c3aecc501c03b92e259fe0ae1c4d472033b7e5 /src | |
parent | 1a248b1b932e2c7c42e25993d921e78c52aa4bcf (diff) | |
download | qt-creator-ddefe062c73e35def585f8fc6c90a4f18e47c0f4.tar.gz |
Fix up QProcess::waitForFinished()
waitForFinish returns false if the process is no longer running at
the time of the call. Handle that throughout the codebase.
Change-Id: Ia7194095454e82efbd4eb88f2d55926bdd09e094
Reviewed-by: hjk <hjk@theqtcompany.com>
Diffstat (limited to 'src')
38 files changed, 373 insertions, 488 deletions
diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp index 71a30aa91b..a57c829a22 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 565da03c6a..0b17543f93 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 9246366b68..3ee3233936 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 5b5d433f45..42b32bacbd 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 e11fc052bc..352705dfae 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 7883df405f..698dc98aa0 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 06ace3cb36..32b4596a09 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 764ce3c834..70c9dc9d92 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 7a5f6b6dee..062c13e7a4 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 470b8a4115..cfb8f69bd5 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 d35a1998e3..a8a778cd39 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 2d5e5b579f..ec29ca4b5b 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 fb3c9edf17..b2e09e64cf 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 c3293afbb8..ea7ea11431 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 508a511742..c44c2e2b55 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 ed552ae720..bdbb34c211 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 c29e6e13ab..a9b9890493 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 98c3695342..87f3c07a93 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 ec6ac3d799..986a9cb30f 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 e5716e4a15..c02a87f9c2 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 4769eecf3a..11319c47c9 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 d946efbe4a..109592bd62 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 72069fb91b..47c4e2c7a7 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 9494b356bc..a5c0bf3965 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 7c8c27e780..b7f5f56ccb 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 b868095983..e1a7ec67b6 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 0bf126ed3a..37beaa309d 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 e397454803..4c14e9a5bb 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 fa1e83cdab..59487384c1 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 77f9961e2a..05c6535ec6 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 e657c0dea8..627dc67206 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 310d4f5cce..1d8df3ac33 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 2c1578b0a6..3075188388 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 89eb5f62e1..a12fe364ce 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 1231bd41a5..545d04101c 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 9e990bfdc7..48178d7cf9 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 73f781135c..a9a68011bc 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 b911c8ae09..ab257ad4b1 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; } |