forked from qt-creator/qt-creator
		
	VCS: Fix time-out handling for synchronous processes.
Introduce static utilities to Utils::SynchronousProcess for synchronous processes that mimicks the handling of Utils::SynchronousProcess (apply timeout after no more data are available on stdout/stderr as opposed to waitForFinished()). Task-number: QTCREATORBUG-777
This commit is contained in:
		| @@ -49,6 +49,7 @@ | ||||
|  | ||||
| #include <texteditor/itexteditor.h> | ||||
| #include <utils/qtcassert.h> | ||||
| #include <utils/synchronousprocess.h> | ||||
| #include <vcsbase/vcsbaseeditor.h> | ||||
| #include <vcsbase/vcsbaseoutputwindow.h> | ||||
|  | ||||
| @@ -1042,22 +1043,16 @@ bool GitClient::synchronousGit(const QString &workingDirectory, | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (!process.waitForFinished(m_settings.timeoutSeconds * 1000)) { | ||||
|         if (errorText) | ||||
|             *errorText = GitCommand::msgTimeout(m_settings.timeoutSeconds).toLocal8Bit(); | ||||
|         GitCommand::stopProcess(process); | ||||
|     if (!Utils::SynchronousProcess::readDataFromProcess(process, m_settings.timeoutSeconds * 1000, | ||||
|                                                         outputText, errorText)) { | ||||
|         *errorText->append(GitCommand::msgTimeout(m_settings.timeoutSeconds).toLocal8Bit()); | ||||
|         Utils::SynchronousProcess::stopProcess(process); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (outputText) | ||||
|         *outputText = process.readAllStandardOutput(); | ||||
|  | ||||
|     if (errorText) | ||||
|         *errorText = process.readAllStandardError(); | ||||
|  | ||||
|     if (Git::Constants::debug) | ||||
|         qDebug() << "synchronousGit ex=" << process.exitCode(); | ||||
|     return process.exitCode() == 0; | ||||
|         qDebug() << "synchronousGit ex=" << process.exitStatus() << process.exitCode(); | ||||
|     return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; | ||||
| } | ||||
|  | ||||
| static inline int | ||||
| @@ -1546,7 +1541,8 @@ QString GitClient::readConfig(const QString &workingDirectory, const QStringList | ||||
|     arguments << QLatin1String("config") << configVar; | ||||
|  | ||||
|     QByteArray outputText; | ||||
|     if (synchronousGit(workingDirectory, arguments, &outputText, 0, false)) | ||||
|     QByteArray errorText; | ||||
|     if (synchronousGit(workingDirectory, arguments, &outputText, &errorText, false)) | ||||
|         return commandOutputFromLocal8Bit(outputText); | ||||
|     return QString(); | ||||
| } | ||||
|   | ||||
| @@ -230,8 +230,8 @@ private: | ||||
|  | ||||
|     bool synchronousGit(const QString &workingDirectory, | ||||
|                         const QStringList &arguments, | ||||
|                         QByteArray* outputText = 0, | ||||
|                         QByteArray* errorText = 0, | ||||
|                         QByteArray* outputText, | ||||
|                         QByteArray* errorText, | ||||
|                         bool logCommandToWindow = true); | ||||
|     // determine version as '(major << 16) + (minor << 8) + patch' or 0. | ||||
|     unsigned synchronousGitVersion(bool silent, QString *errorMessage = 0); | ||||
|   | ||||
| @@ -33,6 +33,7 @@ | ||||
| #include <coreplugin/icore.h> | ||||
| #include <coreplugin/progressmanager/progressmanager.h> | ||||
| #include <extensionsystem/pluginmanager.h> | ||||
| #include <utils/synchronousprocess.h> | ||||
|  | ||||
| #include <QtCore/QDebug> | ||||
| #include <QtCore/QProcess> | ||||
| @@ -117,17 +118,6 @@ QString GitCommand::msgTimeout(int seconds) | ||||
|     return tr("Error: Git timed out after %1s.").arg(seconds); | ||||
| } | ||||
|  | ||||
| bool GitCommand::stopProcess(QProcess &p) | ||||
| { | ||||
|     if (p.state() != QProcess::Running) | ||||
|         return true; | ||||
|     p.terminate(); | ||||
|     if (p.waitForFinished(300)) | ||||
|         return true; | ||||
|     p.kill(); | ||||
|     return p.waitForFinished(300); | ||||
| } | ||||
|  | ||||
| void GitCommand::run() | ||||
| { | ||||
|     if (Git::Constants::debug) | ||||
| @@ -138,7 +128,8 @@ void GitCommand::run() | ||||
|  | ||||
|     process.setEnvironment(m_environment); | ||||
|  | ||||
|     QByteArray output; | ||||
|     QByteArray stdOut; | ||||
|     QByteArray stdErr; | ||||
|     QString error; | ||||
|  | ||||
|     const int count = m_jobs.size(); | ||||
| @@ -156,20 +147,20 @@ void GitCommand::run() | ||||
|  | ||||
|         process.closeWriteChannel(); | ||||
|         const int timeOutSeconds = m_jobs.at(j).timeout; | ||||
|         if (!process.waitForFinished(timeOutSeconds * 1000)) { | ||||
|             stopProcess(process); | ||||
|         if (!Utils::SynchronousProcess::readDataFromProcess(process, timeOutSeconds * 1000, | ||||
|                                                             &stdOut, &stdErr)) { | ||||
|             Utils::SynchronousProcess::stopProcess(process); | ||||
|             ok = false; | ||||
|             error += msgTimeout(timeOutSeconds); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         output += process.readAllStandardOutput(); | ||||
|         error += QString::fromLocal8Bit(process.readAllStandardError()); | ||||
|         error += QString::fromLocal8Bit(stdErr); | ||||
|         switch (m_reportTerminationMode) { | ||||
|         case NoReport: | ||||
|             break; | ||||
|         case ReportStdout: | ||||
|             output += msgTermination(process.exitCode(), m_binaryPath, m_jobs.at(j).arguments).toUtf8(); | ||||
|             stdOut += msgTermination(process.exitCode(), m_binaryPath, m_jobs.at(j).arguments).toUtf8(); | ||||
|             break; | ||||
|         case ReportStderr: | ||||
|             error += msgTermination(process.exitCode(), m_binaryPath, m_jobs.at(j).arguments); | ||||
| @@ -178,16 +169,16 @@ void GitCommand::run() | ||||
|     } | ||||
|  | ||||
|     // Special hack: Always produce output for diff | ||||
|     if (ok && output.isEmpty() && m_jobs.front().arguments.at(0) == QLatin1String("diff")) { | ||||
|         output += "The file does not differ from HEAD"; | ||||
|     if (ok && stdOut.isEmpty() && m_jobs.front().arguments.at(0) == QLatin1String("diff")) { | ||||
|         stdOut += "The file does not differ from HEAD"; | ||||
|     } else { | ||||
|         // @TODO: Remove, see below | ||||
|         if (ok && m_jobs.front().arguments.at(0) == QLatin1String("status")) | ||||
|             removeColorCodes(&output); | ||||
|             removeColorCodes(&stdOut); | ||||
|     } | ||||
|  | ||||
|     if (ok && !output.isEmpty()) | ||||
|         emit outputData(output); | ||||
|     if (ok && !stdOut.isEmpty()) | ||||
|         emit outputData(stdOut); | ||||
|  | ||||
|     if (!error.isEmpty()) | ||||
|         emit errorText(error); | ||||
|   | ||||
| @@ -71,8 +71,6 @@ public: | ||||
|     void setTerminationReportMode(TerminationReportMode m); | ||||
|  | ||||
|     static QString msgTimeout(int seconds); | ||||
|     // Helper to kill a process by SIGNAL first, allowing for cleanup | ||||
|     static bool stopProcess(QProcess &p); | ||||
|  | ||||
| private: | ||||
|     void run(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user