forked from qt-creator/qt-creator
Utils: Base SynchronousProcess on QtcProcess
This is the last intermediate step before unification to keep the merge small. Change-Id: I5b320f9db4c467c49a384f665cea5e16bfef4f60 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -2037,7 +2037,6 @@ public:
|
|||||||
void clearForRun();
|
void clearForRun();
|
||||||
|
|
||||||
QTextCodec *m_codec = QTextCodec::codecForLocale();
|
QTextCodec *m_codec = QTextCodec::codecForLocale();
|
||||||
QtcProcess m_process;
|
|
||||||
QTimer m_timer;
|
QTimer m_timer;
|
||||||
QEventLoop m_eventLoop;
|
QEventLoop m_eventLoop;
|
||||||
SynchronousProcessResponse m_result;
|
SynchronousProcessResponse m_result;
|
||||||
@@ -2072,16 +2071,14 @@ SynchronousProcess::SynchronousProcess() :
|
|||||||
{
|
{
|
||||||
d->m_timer.setInterval(1000);
|
d->m_timer.setInterval(1000);
|
||||||
connect(&d->m_timer, &QTimer::timeout, this, &SynchronousProcess::slotTimeout);
|
connect(&d->m_timer, &QTimer::timeout, this, &SynchronousProcess::slotTimeout);
|
||||||
connect(&d->m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
connect(this, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
||||||
this, &SynchronousProcess::finished);
|
this, &SynchronousProcess::slotFinished);
|
||||||
connect(&d->m_process, &QProcess::errorOccurred, this, &SynchronousProcess::error);
|
connect(this, &QProcess::errorOccurred, this, &SynchronousProcess::error);
|
||||||
connect(&d->m_process, &QProcess::readyReadStandardOutput,
|
connect(this, &QProcess::readyReadStandardOutput, this, [this] {
|
||||||
this, [this]() {
|
|
||||||
d->m_hangTimerCount = 0;
|
d->m_hangTimerCount = 0;
|
||||||
processStdOut(true);
|
processStdOut(true);
|
||||||
});
|
});
|
||||||
connect(&d->m_process, &QProcess::readyReadStandardError,
|
connect(this, &QProcess::readyReadStandardError, this, [this] {
|
||||||
this, [this]() {
|
|
||||||
d->m_hangTimerCount = 0;
|
d->m_hangTimerCount = 0;
|
||||||
processStdErr(true);
|
processStdErr(true);
|
||||||
});
|
});
|
||||||
@@ -2090,7 +2087,7 @@ SynchronousProcess::SynchronousProcess() :
|
|||||||
SynchronousProcess::~SynchronousProcess()
|
SynchronousProcess::~SynchronousProcess()
|
||||||
{
|
{
|
||||||
disconnect(&d->m_timer, nullptr, this, nullptr);
|
disconnect(&d->m_timer, nullptr, this, nullptr);
|
||||||
disconnect(&d->m_process, nullptr, this, nullptr);
|
disconnect(this, nullptr, this, nullptr);
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2102,78 +2099,23 @@ void SynchronousProcess::setTimeoutS(int timeoutS)
|
|||||||
d->m_maxHangTimerCount = INT_MAX / 1000;
|
d->m_maxHangTimerCount = INT_MAX / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SynchronousProcess::timeoutS() const
|
|
||||||
{
|
|
||||||
return d->m_maxHangTimerCount == (INT_MAX / 1000) ? -1 : d->m_maxHangTimerCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SynchronousProcess::setCodec(QTextCodec *c)
|
void SynchronousProcess::setCodec(QTextCodec *c)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(c, return);
|
QTC_ASSERT(c, return);
|
||||||
d->m_codec = c;
|
d->m_codec = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextCodec *SynchronousProcess::codec() const
|
|
||||||
{
|
|
||||||
return d->m_codec;
|
|
||||||
}
|
|
||||||
|
|
||||||
Environment SynchronousProcess::environment() const
|
|
||||||
{
|
|
||||||
return d->m_process.environment();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SynchronousProcess::timeOutMessageBoxEnabled() const
|
|
||||||
{
|
|
||||||
return d->m_timeOutMessageBoxEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SynchronousProcess::setTimeOutMessageBoxEnabled(bool v)
|
void SynchronousProcess::setTimeOutMessageBoxEnabled(bool v)
|
||||||
{
|
{
|
||||||
d->m_timeOutMessageBoxEnabled = v;
|
d->m_timeOutMessageBoxEnabled = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynchronousProcess::setEnvironment(const Environment &e)
|
|
||||||
{
|
|
||||||
d->m_process.setEnvironment(Environment(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SynchronousProcess::setDisableUnixTerminal()
|
|
||||||
{
|
|
||||||
d->m_process.setDisableUnixTerminal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SynchronousProcess::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter)
|
void SynchronousProcess::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(interpreter, return);
|
QTC_ASSERT(interpreter, return);
|
||||||
d->m_exitCodeInterpreter = interpreter;
|
d->m_exitCodeInterpreter = interpreter;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExitCodeInterpreter SynchronousProcess::exitCodeInterpreter() const
|
|
||||||
{
|
|
||||||
return d->m_exitCodeInterpreter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SynchronousProcess::setWorkingDirectory(const QString &workingDirectory)
|
|
||||||
{
|
|
||||||
d->m_process.setWorkingDirectory(workingDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString SynchronousProcess::workingDirectory() const
|
|
||||||
{
|
|
||||||
return d->m_process.workingDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
QProcess::ProcessChannelMode SynchronousProcess::processChannelMode () const
|
|
||||||
{
|
|
||||||
return d->m_process.processChannelMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SynchronousProcess::setProcessChannelMode(QProcess::ProcessChannelMode m)
|
|
||||||
{
|
|
||||||
d->m_process.setProcessChannelMode(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
static bool isGuiThread()
|
static bool isGuiThread()
|
||||||
{
|
{
|
||||||
@@ -2187,8 +2129,8 @@ SynchronousProcessResponse SynchronousProcess::run(const CommandLine &cmd,
|
|||||||
// FIXME: Implement properly
|
// FIXME: Implement properly
|
||||||
if (cmd.executable().needsDevice()) {
|
if (cmd.executable().needsDevice()) {
|
||||||
QtcProcess proc;
|
QtcProcess proc;
|
||||||
proc.setEnvironment(Environment(d->m_process.environment()));
|
proc.setEnvironment(Environment(environment()));
|
||||||
proc.setWorkingDirectory(d->m_process.workingDirectory());
|
proc.setWorkingDirectory(workingDirectory());
|
||||||
proc.setCommand(cmd);
|
proc.setCommand(cmd);
|
||||||
|
|
||||||
// writeData ?
|
// writeData ?
|
||||||
@@ -2215,15 +2157,15 @@ SynchronousProcessResponse SynchronousProcess::run(const CommandLine &cmd,
|
|||||||
// using QProcess::start() and passing program, args and OpenMode results in a different
|
// using QProcess::start() and passing program, args and OpenMode results in a different
|
||||||
// quoting of arguments than using QProcess::setArguments() beforehand and calling start()
|
// quoting of arguments than using QProcess::setArguments() beforehand and calling start()
|
||||||
// only with the OpenMode
|
// only with the OpenMode
|
||||||
d->m_process.setCommand(cmd);
|
setCommand(cmd);
|
||||||
if (!writeData.isEmpty()) {
|
if (!writeData.isEmpty()) {
|
||||||
connect(&d->m_process, &QProcess::started, this, [this, writeData] {
|
connect(this, &QProcess::started, this, [this, writeData] {
|
||||||
d->m_process.write(writeData);
|
write(writeData);
|
||||||
d->m_process.closeWriteChannel();
|
closeWriteChannel();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
d->m_process.setOpenMode(writeData.isEmpty() ? QIODevice::ReadOnly : QIODevice::ReadWrite);
|
setOpenMode(writeData.isEmpty() ? QIODevice::ReadOnly : QIODevice::ReadWrite);
|
||||||
d->m_process.start();
|
start();
|
||||||
|
|
||||||
// On Windows, start failure is triggered immediately if the
|
// On Windows, start failure is triggered immediately if the
|
||||||
// executable cannot be found in the path. Do not start the
|
// executable cannot be found in the path. Do not start the
|
||||||
@@ -2256,8 +2198,8 @@ SynchronousProcessResponse SynchronousProcess::runBlocking(const CommandLine &cm
|
|||||||
// FIXME: Implement properly
|
// FIXME: Implement properly
|
||||||
if (cmd.executable().needsDevice()) {
|
if (cmd.executable().needsDevice()) {
|
||||||
QtcProcess proc;
|
QtcProcess proc;
|
||||||
proc.setEnvironment(Environment(d->m_process.environment()));
|
proc.setEnvironment(Environment(environment()));
|
||||||
proc.setWorkingDirectory(d->m_process.workingDirectory());
|
proc.setWorkingDirectory(workingDirectory());
|
||||||
proc.setCommand(cmd);
|
proc.setCommand(cmd);
|
||||||
|
|
||||||
// writeData ?
|
// writeData ?
|
||||||
@@ -2281,32 +2223,32 @@ SynchronousProcessResponse SynchronousProcess::runBlocking(const CommandLine &cm
|
|||||||
d->clearForRun();
|
d->clearForRun();
|
||||||
|
|
||||||
d->m_binary = cmd.executable();
|
d->m_binary = cmd.executable();
|
||||||
d->m_process.setOpenMode(QIODevice::ReadOnly);
|
setOpenMode(QIODevice::ReadOnly);
|
||||||
d->m_process.setCommand(cmd);
|
setCommand(cmd);
|
||||||
d->m_process.start();
|
start();
|
||||||
if (!d->m_process.waitForStarted(d->m_maxHangTimerCount * 1000)) {
|
if (!waitForStarted(d->m_maxHangTimerCount * 1000)) {
|
||||||
d->m_result.result = SynchronousProcessResponse::StartFailed;
|
d->m_result.result = SynchronousProcessResponse::StartFailed;
|
||||||
return d->m_result;
|
return d->m_result;
|
||||||
}
|
}
|
||||||
d->m_process.closeWriteChannel();
|
closeWriteChannel();
|
||||||
if (!d->m_process.waitForFinished(d->m_maxHangTimerCount * 1000)) {
|
if (!waitForFinished(d->m_maxHangTimerCount * 1000)) {
|
||||||
d->m_result.result = SynchronousProcessResponse::Hang;
|
d->m_result.result = SynchronousProcessResponse::Hang;
|
||||||
d->m_process.terminate();
|
terminate();
|
||||||
if (!d->m_process.waitForFinished(1000)) {
|
if (!waitForFinished(1000)) {
|
||||||
d->m_process.kill();
|
kill();
|
||||||
d->m_process.waitForFinished(1000);
|
waitForFinished(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->m_process.state() != QProcess::NotRunning)
|
if (state() != QProcess::NotRunning)
|
||||||
return d->m_result;
|
return d->m_result;
|
||||||
|
|
||||||
d->m_result.exitCode = d->m_process.exitCode();
|
d->m_result.exitCode = exitCode();
|
||||||
if (d->m_result.result == SynchronousProcessResponse::StartFailed) {
|
if (d->m_result.result == SynchronousProcessResponse::StartFailed) {
|
||||||
if (d->m_process.exitStatus() != QProcess::NormalExit)
|
if (exitStatus() != QProcess::NormalExit)
|
||||||
d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
|
d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
|
||||||
else
|
else
|
||||||
d->m_result.result = (exitCodeInterpreter())(d->m_result.exitCode);
|
d->m_result.result = d->m_exitCodeInterpreter(d->m_result.exitCode);
|
||||||
}
|
}
|
||||||
processStdOut(false);
|
processStdOut(false);
|
||||||
processStdErr(false);
|
processStdErr(false);
|
||||||
@@ -2327,11 +2269,6 @@ void SynchronousProcess::setStdErrCallback(const std::function<void (const QStri
|
|||||||
d->m_stdErr.outputCallback = callback;
|
d->m_stdErr.outputCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SynchronousProcess::stopProcess()
|
|
||||||
{
|
|
||||||
return d->m_process.stopProcess();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SynchronousProcess::slotTimeout()
|
void SynchronousProcess::slotTimeout()
|
||||||
{
|
{
|
||||||
if (!d->m_waitingForUser && (++d->m_hangTimerCount > d->m_maxHangTimerCount)) {
|
if (!d->m_waitingForUser && (++d->m_hangTimerCount > d->m_maxHangTimerCount)) {
|
||||||
@@ -2341,7 +2278,7 @@ void SynchronousProcess::slotTimeout()
|
|||||||
const bool terminate = !d->m_timeOutMessageBoxEnabled || askToKill(d->m_binary.toString());
|
const bool terminate = !d->m_timeOutMessageBoxEnabled || askToKill(d->m_binary.toString());
|
||||||
d->m_waitingForUser = false;
|
d->m_waitingForUser = false;
|
||||||
if (terminate) {
|
if (terminate) {
|
||||||
d->m_process.stopProcess();
|
stopProcess();
|
||||||
d->m_result.result = SynchronousProcessResponse::Hang;
|
d->m_result.result = SynchronousProcessResponse::Hang;
|
||||||
} else {
|
} else {
|
||||||
d->m_hangTimerCount = 0;
|
d->m_hangTimerCount = 0;
|
||||||
@@ -2352,7 +2289,7 @@ void SynchronousProcess::slotTimeout()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e)
|
void SynchronousProcess::slotFinished(int exitCode, QProcess::ExitStatus e)
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << Q_FUNC_INFO << exitCode << e;
|
qDebug() << Q_FUNC_INFO << exitCode << e;
|
||||||
@@ -2388,13 +2325,13 @@ void SynchronousProcess::error(QProcess::ProcessError e)
|
|||||||
void SynchronousProcess::processStdOut(bool emitSignals)
|
void SynchronousProcess::processStdOut(bool emitSignals)
|
||||||
{
|
{
|
||||||
// Handle binary data
|
// Handle binary data
|
||||||
d->m_stdOut.append(d->m_process.readAllStandardOutput(), emitSignals);
|
d->m_stdOut.append(readAllStandardOutput(), emitSignals);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynchronousProcess::processStdErr(bool emitSignals)
|
void SynchronousProcess::processStdErr(bool emitSignals)
|
||||||
{
|
{
|
||||||
// Handle binary data
|
// Handle binary data
|
||||||
d->m_stdErr.append(d->m_process.readAllStandardError(), emitSignals);
|
d->m_stdErr.append(readAllStandardError(), emitSignals);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -230,7 +230,7 @@ QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessRes
|
|||||||
using ExitCodeInterpreter = std::function<SynchronousProcessResponse::Result(int /*exitCode*/)>;
|
using ExitCodeInterpreter = std::function<SynchronousProcessResponse::Result(int /*exitCode*/)>;
|
||||||
QTCREATOR_UTILS_EXPORT SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code);
|
QTCREATOR_UTILS_EXPORT SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code);
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT SynchronousProcess : public QObject
|
class QTCREATOR_UTILS_EXPORT SynchronousProcess : public QtcProcess
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -240,28 +240,10 @@ public:
|
|||||||
/* Timeout for hanging processes (triggers after no more output
|
/* Timeout for hanging processes (triggers after no more output
|
||||||
* occurs on stderr/stdout). */
|
* occurs on stderr/stdout). */
|
||||||
void setTimeoutS(int timeoutS);
|
void setTimeoutS(int timeoutS);
|
||||||
int timeoutS() const;
|
|
||||||
|
|
||||||
void setCodec(QTextCodec *c);
|
void setCodec(QTextCodec *c);
|
||||||
QTextCodec *codec() const;
|
|
||||||
|
|
||||||
QProcess::ProcessChannelMode processChannelMode () const;
|
|
||||||
void setProcessChannelMode(QProcess::ProcessChannelMode m);
|
|
||||||
|
|
||||||
bool timeOutMessageBoxEnabled() const;
|
|
||||||
void setTimeOutMessageBoxEnabled(bool);
|
void setTimeOutMessageBoxEnabled(bool);
|
||||||
|
|
||||||
Environment environment() const;
|
|
||||||
void setEnvironment(const Environment &);
|
|
||||||
|
|
||||||
void setWorkingDirectory(const QString &workingDirectory);
|
|
||||||
QString workingDirectory() const;
|
|
||||||
|
|
||||||
// Unix: Do not give the child process a terminal for input prompting.
|
|
||||||
void setDisableUnixTerminal();
|
|
||||||
|
|
||||||
void setExitCodeInterpreter(const ExitCodeInterpreter &interpreter);
|
void setExitCodeInterpreter(const ExitCodeInterpreter &interpreter);
|
||||||
ExitCodeInterpreter exitCodeInterpreter() const;
|
|
||||||
|
|
||||||
// Starts a nested event loop and runs the command
|
// Starts a nested event loop and runs the command
|
||||||
SynchronousProcessResponse run(const CommandLine &cmd, const QByteArray &writeData = {});
|
SynchronousProcessResponse run(const CommandLine &cmd, const QByteArray &writeData = {});
|
||||||
@@ -271,11 +253,9 @@ public:
|
|||||||
void setStdOutCallback(const std::function<void(const QString &)> &callback);
|
void setStdOutCallback(const std::function<void(const QString &)> &callback);
|
||||||
void setStdErrCallback(const std::function<void(const QString &)> &callback);
|
void setStdErrCallback(const std::function<void(const QString &)> &callback);
|
||||||
|
|
||||||
bool stopProcess();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void slotTimeout();
|
void slotTimeout();
|
||||||
void finished(int exitCode, QProcess::ExitStatus e);
|
void slotFinished(int exitCode, QProcess::ExitStatus e);
|
||||||
void error(QProcess::ProcessError);
|
void error(QProcess::ProcessError);
|
||||||
void processStdOut(bool emitSignals);
|
void processStdOut(bool emitSignals);
|
||||||
void processStdErr(bool emitSignals);
|
void processStdErr(bool emitSignals);
|
||||||
|
Reference in New Issue
Block a user