ProcessInterface: Add sendControlSignal() method

It substitutes terminate, kill, interrupt and kickoffProcess
methods.

Task-number: QTCREATORBUG-27358
Change-Id: I9e952c2f4c1a7e76339366566f2c804a3df30347
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Jarek Kobus
2022-04-11 19:45:04 +02:00
parent 25be242c6f
commit 7c8b5648fe
5 changed files with 80 additions and 71 deletions

View File

@@ -71,6 +71,13 @@ public:
QString m_errorString;
};
enum class ControlSignal {
Terminate,
Kill,
Interrupt,
KickOff
};
class QTCREATOR_UTILS_EXPORT ProcessInterface : public QObject
{
Q_OBJECT
@@ -80,11 +87,8 @@ public:
ProcessInterface(ProcessSetupData::Ptr setup) : m_setup(setup) {}
virtual void start() = 0;
virtual void interrupt() = 0;
virtual void terminate() = 0;
virtual void kill() = 0;
virtual qint64 write(const QByteArray &data) = 0;
virtual void sendControlSignal(ControlSignal controlSignal) = 0;
virtual QProcess::ProcessState state() const = 0;
@@ -92,8 +96,6 @@ public:
virtual bool waitForReadyRead(int msecs) = 0;
virtual bool waitForFinished(int msecs) = 0;
virtual void kickoffProcess();
signals:
void started(qint64 processId, qint64 applicationMainThreadId = 0);
void readyRead(const QByteArray &outputData, const QByteArray &errorData);
@@ -121,9 +123,6 @@ public:
}
void start() override { m_target->start(); }
void interrupt() override { m_target->interrupt(); }
void terminate() override { m_target->terminate(); }
void kill() override { m_target->kill(); }
qint64 write(const QByteArray &data) override { return m_target->write(data); }
@@ -133,8 +132,6 @@ public:
bool waitForReadyRead(int msecs) override { return m_target->waitForReadyRead(msecs); }
bool waitForFinished(int msecs) override { return m_target->waitForFinished(msecs); }
void kickoffProcess() override { m_target->kickoffProcess(); }
protected:
ProcessInterface *m_target;
};

View File

@@ -347,10 +347,23 @@ public:
}
~QProcessImpl() final { ProcessReaper::reap(m_process); }
void interrupt() final { ProcessHelper::interruptProcess(m_process); }
void terminate() final { ProcessHelper::terminateProcess(m_process); }
void kill() final { m_process->kill(); }
qint64 write(const QByteArray &data) final { return m_process->write(data); }
void sendControlSignal(ControlSignal controlSignal) final {
switch (controlSignal) {
case ControlSignal::Terminate:
ProcessHelper::terminateProcess(m_process);
break;
case ControlSignal::Kill:
m_process->kill();
break;
case ControlSignal::Interrupt:
ProcessHelper::interruptProcess(m_process);
break;
case ControlSignal::KickOff:
QTC_CHECK(false);
break;
}
}
QProcess::ProcessState state() const final { return m_process->state(); }
@@ -432,14 +445,24 @@ public:
m_handle = nullptr;
}
void interrupt() final
{
if (m_setup->m_useCtrlCStub) // bypass launcher and interrupt directly
ProcessHelper::interruptPid(m_handle->processId());
}
void terminate() final { m_handle->terminate(); }
void kill() final { m_handle->kill(); }
qint64 write(const QByteArray &data) final { return m_handle->write(data); }
void sendControlSignal(ControlSignal controlSignal) final {
switch (controlSignal) {
case ControlSignal::Terminate:
m_handle->terminate();
break;
case ControlSignal::Kill:
m_handle->kill();
break;
case ControlSignal::Interrupt:
if (m_setup->m_useCtrlCStub) // bypass launcher and interrupt directly
ProcessHelper::interruptPid(m_handle->processId());
break;
case ControlSignal::KickOff:
QTC_CHECK(false);
break;
}
}
QProcess::ProcessState state() const final { return m_handle->state(); }
@@ -599,11 +622,6 @@ ProcessResult QtcProcessPrivate::interpretExitCode(int exitCode)
} // Internal
void ProcessInterface::kickoffProcess()
{
QTC_CHECK(false);
}
/*!
\class Utils::QtcProcess
@@ -805,13 +823,25 @@ void QtcProcess::start()
void QtcProcess::terminate()
{
if (d->m_process)
d->m_process->terminate();
d->m_process->sendControlSignal(ControlSignal::Terminate);
}
void QtcProcess::kill()
{
if (d->m_process)
d->m_process->sendControlSignal(ControlSignal::Kill);
}
void QtcProcess::interrupt()
{
if (d->m_process)
d->m_process->interrupt();
d->m_process->sendControlSignal(ControlSignal::Interrupt);
}
void QtcProcess::kickoffProcess()
{
if (d->m_process)
d->m_process->sendControlSignal(ControlSignal::KickOff);
}
bool QtcProcess::startDetached(const CommandLine &cmd, const FilePath &workingDirectory, qint64 *pid)
@@ -1115,12 +1145,6 @@ Environment QtcProcess::systemEnvironmentForBinary(const FilePath &filePath)
return Environment::systemEnvironment();
}
void QtcProcess::kickoffProcess()
{
if (d->m_process)
d->m_process->kickoffProcess();
}
qint64 QtcProcess::applicationMainThreadId() const
{
return d->m_applicationMainThreadId;
@@ -1181,12 +1205,6 @@ QByteArray QtcProcess::readAllStandardError()
return buf;
}
void QtcProcess::kill()
{
if (d->m_process)
d->m_process->kill();
}
qint64 QtcProcess::write(const QByteArray &input)
{
QTC_ASSERT(processMode() == ProcessMode::Writer, return -1);

View File

@@ -60,9 +60,11 @@ public:
// ProcessInterface related
virtual void start();
virtual void interrupt();
virtual void terminate();
virtual void kill();
virtual void interrupt();
void kickoffProcess();
void close();
virtual QByteArray readAllStandardOutput();
@@ -70,6 +72,8 @@ public:
virtual qint64 write(const QByteArray &input);
virtual qint64 processId() const;
qint64 applicationMainThreadId() const;
virtual QProcess::ProcessState state() const;
virtual ProcessResultData resultData() const;
@@ -83,9 +87,6 @@ public:
bool waitForReadyRead(int msecs = 30000);
bool waitForFinished(int msecs = 30000);
void kickoffProcess();
qint64 applicationMainThreadId() const;
// ProcessSetupData related
void setProcessImpl(ProcessImpl processImpl);

View File

@@ -435,25 +435,29 @@ void TerminalImpl::cleanupAfterStartFailure(const QString &errorMessage)
d->m_tempFile = nullptr;
}
void TerminalImpl::kickoffProcess()
void TerminalImpl::sendControlSignal(ControlSignal controlSignal)
{
#ifdef Q_OS_WIN
// Not used.
#else
if (d->m_stubSocket && d->m_stubSocket->isWritable()) {
d->m_stubSocket->write("c", 1);
d->m_stubSocket->flush();
switch (controlSignal) {
case Utils::ControlSignal::Terminate:
case Utils::ControlSignal::Kill:
stopProcess();
break;
case Utils::ControlSignal::Interrupt:
sendCommand('i');
break;
case Utils::ControlSignal::KickOff:
sendCommand('c');
break;
}
#endif
}
void TerminalImpl::interrupt()
void TerminalImpl::sendCommand(char c)
{
#ifdef Q_OS_WIN
// Not used.
Q_UNUSED(c)
#else
if (d->m_stubSocket && d->m_stubSocket->isWritable()) {
d->m_stubSocket->write("i", 1);
d->m_stubSocket->write(&c, 1);
d->m_stubSocket->flush();
}
#endif
@@ -467,10 +471,7 @@ void TerminalImpl::killProcess()
cleanupInferior();
}
#else
if (d->m_stubSocket && d->m_stubSocket->isWritable()) {
d->m_stubSocket->write("k", 1);
d->m_stubSocket->flush();
}
sendCommand('k');
#endif
d->m_processId = 0;
}
@@ -484,10 +485,7 @@ void TerminalImpl::killStub()
cleanupStub();
}
#else
if (d->m_stubSocket && d->m_stubSocket->isWritable()) {
d->m_stubSocket->write("s", 1);
d->m_stubSocket->flush();
}
sendCommand('s');
stubServerShutdown();
#endif
}

View File

@@ -45,10 +45,9 @@ public:
TerminalImpl();
~TerminalImpl() final;
void start() final;
qint64 write(const QByteArray &) final { QTC_CHECK(false); return -1; }
void terminate() final { stopProcess(); }
void kill() final { stopProcess(); }
void sendControlSignal(ControlSignal controlSignal) final;
// intentionally no-op without an assert
bool waitForStarted(int) final { return false; }
@@ -56,13 +55,8 @@ public:
// intentionally no-op without an assert
bool waitForFinished(int) final { return false; }
void start() final;
QProcess::ProcessState state() const final;
void kickoffProcess() final; // only debugger terminal, only non-windows
void interrupt() final; // only debugger terminal, only non-windows
private:
// OK, however, impl looks a bit different (!= NotRunning vs == Running).
// Most probably changing it into (== Running) should be OK.
@@ -81,6 +75,7 @@ private:
void stubServerShutdown();
void cleanupStub();
void cleanupInferior();
void sendCommand(char c);
class TerminalProcessPrivate *d;
};