Set process state to NotRunning after FailedToStart error

Remove the process in process launcher after error has appeared.
Remove unneeded stopStopProcedure as we are disconnecting from
process' signals inside removeProcess().
In order to behave as much similar to what QProcess does,
provide a test that:
- ensures the FailedToStart error is synchronously emitted
  when waitForStarted is being executed
- ensures that process state is reset to NotRunning after
  FailedToStart error
- 2nd call to start/waitForStarted doesn't block on
  waitForStarted

Change-Id: I139354421d037739f1cc1a2685b66f1e5b6170c8
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Jarek Kobus
2021-08-30 16:29:08 +02:00
parent 73874980ef
commit 15c183fce6
3 changed files with 34 additions and 11 deletions

View File

@@ -213,6 +213,7 @@ bool CallerHandle::shouldFlushFor(SignalType signalType) const
void CallerHandle::handleError(const ErrorSignal *launcherSignal) void CallerHandle::handleError(const ErrorSignal *launcherSignal)
{ {
QTC_ASSERT(isCalledFromCallersThread(), return); QTC_ASSERT(isCalledFromCallersThread(), return);
m_processState = QProcess::NotRunning;
m_error = launcherSignal->error(); m_error = launcherSignal->error();
m_errorString = launcherSignal->errorString(); m_errorString = launcherSignal->errorString();
emit errorOccurred(m_error); emit errorOccurred(m_error);

View File

@@ -71,12 +71,6 @@ public:
} }
} }
void stopStopProcedure()
{
m_stopState = StopState::Inactive;
m_stopTimer->stop();
}
quintptr token() const { return m_token; } quintptr token() const { return m_token; }
ProcessStartHandler *processStartHandler() { return &m_processStartHandler; } ProcessStartHandler *processStartHandler() { return &m_processStartHandler; }
@@ -176,13 +170,11 @@ void LauncherSocketHandler::handleSocketClosed()
void LauncherSocketHandler::handleProcessError() void LauncherSocketHandler::handleProcessError()
{ {
Process * proc = senderProcess(); Process * proc = senderProcess();
if (proc->error() != QProcess::FailedToStart)
return;
proc->stopStopProcedure();
ProcessErrorPacket packet(proc->token()); ProcessErrorPacket packet(proc->token());
packet.error = proc->error(); packet.error = proc->error();
packet.errorString = proc->errorString(); packet.errorString = proc->errorString();
sendPacket(packet); sendPacket(packet);
removeProcess(proc->token());
} }
void LauncherSocketHandler::handleProcessStarted() void LauncherSocketHandler::handleProcessStarted()
@@ -213,7 +205,6 @@ void LauncherSocketHandler::handleReadyReadStandardError()
void LauncherSocketHandler::handleProcessFinished() void LauncherSocketHandler::handleProcessFinished()
{ {
Process * proc = senderProcess(); Process * proc = senderProcess();
proc->stopStopProcedure();
ProcessFinishedPacket packet(proc->token()); ProcessFinishedPacket packet(proc->token());
packet.error = proc->error(); packet.error = proc->error();
packet.errorString = proc->errorString(); packet.errorString = proc->errorString();
@@ -342,7 +333,7 @@ void LauncherSocketHandler::removeProcess(quintptr token)
if (process->state() != QProcess::NotRunning) if (process->state() != QProcess::NotRunning)
process->cancel(); process->cancel();
else else
delete process; process->deleteLater();
} }
Process *LauncherSocketHandler::senderProcess() const Process *LauncherSocketHandler::senderProcess() const

View File

@@ -30,6 +30,7 @@
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <utils/stringutils.h> #include <utils/stringutils.h>
#include <QElapsedTimer>
#include <QRegularExpression> #include <QRegularExpression>
#include <QtTest> #include <QtTest>
@@ -141,6 +142,7 @@ private slots:
void lineCallback(); void lineCallback();
void lineCallbackIntern(); void lineCallbackIntern();
void waitForStartedAndFinished(); void waitForStartedAndFinished();
void notRunningAfterStartingNonExistingProgram();
void cleanupTestCase(); void cleanupTestCase();
@@ -976,6 +978,35 @@ void tst_QtcProcess::waitForStartedAndFinished()
QCOMPARE(process.exitCode(), 0); QCOMPARE(process.exitCode(), 0);
} }
void tst_QtcProcess::notRunningAfterStartingNonExistingProgram()
{
QtcProcess process;
process.setCommand({ FilePath::fromString(
"there_is_a_big_chance_that_executable_with_that_name_does_not_exists"), {} });
int errorCount = 0;
QObject::connect(&process, &QtcProcess::errorOccurred,
[&errorCount](QProcess::ProcessError error) {
++errorCount;
QCOMPARE(error, QProcess::FailedToStart);
});
const int loopCount = 2;
for (int i = 0; i < loopCount; ++i) {
// Work on the same process instance on every iteration
process.start();
QElapsedTimer timer;
timer.start();
const int maxWaitTimeMs = 1000;
QVERIFY(!process.waitForStarted(maxWaitTimeMs));
QVERIFY(timer.elapsed() < maxWaitTimeMs); // shouldn't wait, should finish immediately
QCOMPARE(process.state(), QProcess::NotRunning);
QVERIFY(process.exitCode() != 0);
}
}
QTEST_MAIN(tst_QtcProcess) QTEST_MAIN(tst_QtcProcess)
#include "tst_qtcprocess.moc" #include "tst_qtcprocess.moc"