QtcProcess: Add closeWriteChannel()

Change-Id: I080be230ec420ead2866f9481123125361e57033
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
Jarek Kobus
2023-01-24 07:23:44 +01:00
parent 34fd5b3ced
commit 8e3a22329d
13 changed files with 67 additions and 29 deletions

View File

@@ -90,17 +90,17 @@ void ProcessStartedPacket::doDeserialize(QDataStream &stream)
} }
StopProcessPacket::StopProcessPacket(quintptr token) ControlProcessPacket::ControlProcessPacket(quintptr token)
: LauncherPacket(LauncherPacketType::StopProcess, token) : LauncherPacket(LauncherPacketType::ControlProcess, token)
{ {
} }
void StopProcessPacket::doSerialize(QDataStream &stream) const void ControlProcessPacket::doSerialize(QDataStream &stream) const
{ {
stream << int(signalType); stream << int(signalType);
} }
void StopProcessPacket::doDeserialize(QDataStream &stream) void ControlProcessPacket::doDeserialize(QDataStream &stream)
{ {
int signalTypeInt; int signalTypeInt;
stream >> signalTypeInt; stream >> signalTypeInt;

View File

@@ -21,7 +21,7 @@ enum class LauncherPacketType {
Shutdown, Shutdown,
StartProcess, StartProcess,
WriteIntoProcess, WriteIntoProcess,
StopProcess, ControlProcess,
// launcher -> client packets: // launcher -> client packets:
ProcessStarted, ProcessStarted,
ReadyReadStandardOutput, ReadyReadStandardOutput,
@@ -116,15 +116,16 @@ private:
void doDeserialize(QDataStream &stream) override; void doDeserialize(QDataStream &stream) override;
}; };
class StopProcessPacket : public LauncherPacket class ControlProcessPacket : public LauncherPacket
{ {
public: public:
StopProcessPacket(quintptr token); ControlProcessPacket(quintptr token);
enum class SignalType { enum class SignalType {
Kill, // Calls QProcess::kill Kill, // Calls QProcess::kill
Terminate, // Calls QProcess::terminate Terminate, // Calls QProcess::terminate
Close // Puts the process into the reaper, no confirmation signal is being sent. Close, // Puts the process into the reaper, no confirmation signal is being sent.
CloseWriteChannel
}; };
SignalType signalType = SignalType::Kill; SignalType signalType = SignalType::Kill;

View File

@@ -171,7 +171,7 @@ QProcess::ProcessState CallerHandle::state() const
return m_processState; return m_processState;
} }
void CallerHandle::sendStopPacket(StopProcessPacket::SignalType signalType) void CallerHandle::sendControlPacket(ControlProcessPacket::SignalType signalType)
{ {
if (m_processState == QProcess::NotRunning) if (m_processState == QProcess::NotRunning)
return; return;
@@ -180,7 +180,7 @@ void CallerHandle::sendStopPacket(StopProcessPacket::SignalType signalType)
// we might want to remove posted start packet and finish the process immediately. // we might want to remove posted start packet and finish the process immediately.
// In addition, we may always try to check if correspodning start packet for the m_token // In addition, we may always try to check if correspodning start packet for the m_token
// is still awaiting and do the same (remove the packet from the stack and finish immediately). // is still awaiting and do the same (remove the packet from the stack and finish immediately).
StopProcessPacket packet(m_token); ControlProcessPacket packet(m_token);
packet.signalType = signalType; packet.signalType = signalType;
sendPacket(packet); sendPacket(packet);
} }
@@ -188,19 +188,25 @@ void CallerHandle::sendStopPacket(StopProcessPacket::SignalType signalType)
void CallerHandle::terminate() void CallerHandle::terminate()
{ {
QTC_ASSERT(isCalledFromCallersThread(), return); QTC_ASSERT(isCalledFromCallersThread(), return);
sendStopPacket(StopProcessPacket::SignalType::Terminate); sendControlPacket(ControlProcessPacket::SignalType::Terminate);
} }
void CallerHandle::kill() void CallerHandle::kill()
{ {
QTC_ASSERT(isCalledFromCallersThread(), return); QTC_ASSERT(isCalledFromCallersThread(), return);
sendStopPacket(StopProcessPacket::SignalType::Kill); sendControlPacket(ControlProcessPacket::SignalType::Kill);
} }
void CallerHandle::close() void CallerHandle::close()
{ {
QTC_ASSERT(isCalledFromCallersThread(), return); QTC_ASSERT(isCalledFromCallersThread(), return);
sendStopPacket(StopProcessPacket::SignalType::Close); sendControlPacket(ControlProcessPacket::SignalType::Close);
}
void CallerHandle::closeWriteChannel()
{
QTC_ASSERT(isCalledFromCallersThread(), return);
sendControlPacket(ControlProcessPacket::SignalType::CloseWriteChannel);
} }
qint64 CallerHandle::processId() const qint64 CallerHandle::processId() const

View File

@@ -62,10 +62,11 @@ public:
// Called from caller's or launcher's thread. // Called from caller's or launcher's thread.
QProcess::ProcessState state() const; QProcess::ProcessState state() const;
void sendStopPacket(StopProcessPacket::SignalType signalType); void sendControlPacket(ControlProcessPacket::SignalType signalType);
void terminate(); void terminate();
void kill(); void kill();
void close(); void close();
void closeWriteChannel();
qint64 processId() const; qint64 processId() const;

View File

@@ -19,6 +19,7 @@ int ProcessInterface::controlSignalToInt(ControlSignal controlSignal)
case ControlSignal::Kill: return 9; case ControlSignal::Kill: return 9;
case ControlSignal::Interrupt: return 2; case ControlSignal::Interrupt: return 2;
case ControlSignal::KickOff: QTC_CHECK(false); return 0; case ControlSignal::KickOff: QTC_CHECK(false); return 0;
case ControlSignal::CloseWriteChannel: QTC_CHECK(false); return 0;
} }
return 0; return 0;
} }

View File

@@ -55,7 +55,8 @@ enum class ControlSignal {
Terminate, Terminate,
Kill, Kill,
Interrupt, Interrupt,
KickOff KickOff,
CloseWriteChannel
}; };
enum class ProcessSignalType { enum class ProcessSignalType {

View File

@@ -337,6 +337,9 @@ private:
case ControlSignal::KickOff: case ControlSignal::KickOff:
QTC_CHECK(false); QTC_CHECK(false);
break; break;
case ControlSignal::CloseWriteChannel:
m_process->closeWriteChannel();
break;
} }
} }
@@ -464,6 +467,9 @@ private:
case ControlSignal::KickOff: case ControlSignal::KickOff:
QTC_CHECK(false); QTC_CHECK(false);
break; break;
case ControlSignal::CloseWriteChannel:
m_handle->closeWriteChannel();
break;
} }
} }
@@ -1132,6 +1138,11 @@ void QtcProcess::kickoffProcess()
d->sendControlSignal(ControlSignal::KickOff); d->sendControlSignal(ControlSignal::KickOff);
} }
void QtcProcess::closeWriteChannel()
{
d->sendControlSignal(ControlSignal::CloseWriteChannel);
}
bool QtcProcess::startDetached(const CommandLine &cmd, const FilePath &workingDirectory, qint64 *pid) bool QtcProcess::startDetached(const CommandLine &cmd, const FilePath &workingDirectory, qint64 *pid)
{ {
return QProcess::startDetached(cmd.executable().toUserOutput(), return QProcess::startDetached(cmd.executable().toUserOutput(),

View File

@@ -43,6 +43,7 @@ public:
void kill(); void kill();
void interrupt(); void interrupt();
void kickoffProcess(); void kickoffProcess();
void closeWriteChannel();
void close(); void close();
void stop(); void stop();

View File

@@ -434,6 +434,9 @@ void TerminalImpl::sendControlSignal(ControlSignal controlSignal)
case ControlSignal::KickOff: case ControlSignal::KickOff:
sendCommand('c'); sendCommand('c');
break; break;
case ControlSignal::CloseWriteChannel:
QTC_CHECK(false);
break;
} }
} }

View File

@@ -309,7 +309,11 @@ qint64 DockerProcessImpl::write(const QByteArray &data)
void DockerProcessImpl::sendControlSignal(ControlSignal controlSignal) void DockerProcessImpl::sendControlSignal(ControlSignal controlSignal)
{ {
QTC_ASSERT(m_remotePID, return); QTC_ASSERT(m_remotePID, return);
int signal = controlSignalToInt(controlSignal); if (controlSignal == ControlSignal::CloseWriteChannel) {
m_process.closeWriteChannel();
return;
}
const int signal = controlSignalToInt(controlSignal);
m_devicePrivate->runInShell( m_devicePrivate->runInShell(
{"kill", {QString("-%1").arg(signal), QString("%2").arg(m_remotePID)}}); {"kill", {QString("-%1").arg(signal), QString("%2").arg(m_remotePID)}});
} }

View File

@@ -505,14 +505,19 @@ qint64 SshProcessInterface::write(const QByteArray &data)
return d->m_process.writeRaw(data); return d->m_process.writeRaw(data);
} }
void SshProcessInterface::sendControlSignal(Utils::ControlSignal controlSignal) void SshProcessInterface::sendControlSignal(ControlSignal controlSignal)
{ {
if (controlSignal == ControlSignal::CloseWriteChannel) {
d->m_process.closeWriteChannel();
return;
}
if (d->m_process.usesTerminal()) { if (d->m_process.usesTerminal()) {
switch (controlSignal) { switch (controlSignal) {
case Utils::ControlSignal::Terminate: d->m_process.terminate(); break; case ControlSignal::Terminate: d->m_process.terminate(); break;
case Utils::ControlSignal::Kill: d->m_process.kill(); break; case ControlSignal::Kill: d->m_process.kill(); break;
case Utils::ControlSignal::Interrupt: d->m_process.interrupt(); break; case ControlSignal::Interrupt: d->m_process.interrupt(); break;
case Utils::ControlSignal::KickOff: d->m_process.kickoffProcess(); break; case ControlSignal::KickOff: d->m_process.kickoffProcess(); break;
case ControlSignal::CloseWriteChannel: break;
} }
return; return;
} }
@@ -532,6 +537,7 @@ LinuxProcessInterface::~LinuxProcessInterface()
void LinuxProcessInterface::handleSendControlSignal(ControlSignal controlSignal) void LinuxProcessInterface::handleSendControlSignal(ControlSignal controlSignal)
{ {
QTC_ASSERT(controlSignal != ControlSignal::KickOff, return); QTC_ASSERT(controlSignal != ControlSignal::KickOff, return);
QTC_ASSERT(controlSignal != ControlSignal::CloseWriteChannel, return);
const qint64 pid = processId(); const qint64 pid = processId();
QTC_ASSERT(pid, return); // TODO: try sending a signal based on process name QTC_ASSERT(pid, return); // TODO: try sending a signal based on process name
const QString args = QString::fromLatin1("-%1 -%2") const QString args = QString::fromLatin1("-%1 -%2")

View File

@@ -84,8 +84,8 @@ void LauncherSocketHandler::handleSocketData()
case LauncherPacketType::WriteIntoProcess: case LauncherPacketType::WriteIntoProcess:
handleWritePacket(); handleWritePacket();
break; break;
case LauncherPacketType::StopProcess: case LauncherPacketType::ControlProcess:
handleStopPacket(); handleControlPacket();
break; break;
case LauncherPacketType::Shutdown: case LauncherPacketType::Shutdown:
handleShutdownPacket(); handleShutdownPacket();
@@ -211,7 +211,7 @@ void LauncherSocketHandler::handleWritePacket()
process->write(packet.inputData); process->write(packet.inputData);
} }
void LauncherSocketHandler::handleStopPacket() void LauncherSocketHandler::handleControlPacket()
{ {
Process * const process = m_processes.value(m_packetParser.token()); Process * const process = m_processes.value(m_packetParser.token());
if (!process) { if (!process) {
@@ -220,20 +220,23 @@ void LauncherSocketHandler::handleStopPacket()
logDebug("Got stop request for unknown process"); logDebug("Got stop request for unknown process");
return; return;
} }
const auto packet = LauncherPacket::extractPacket<StopProcessPacket>( const auto packet = LauncherPacket::extractPacket<ControlProcessPacket>(
m_packetParser.token(), m_packetParser.token(),
m_packetParser.packetData()); m_packetParser.packetData());
switch (packet.signalType) { switch (packet.signalType) {
case StopProcessPacket::SignalType::Terminate: case ControlProcessPacket::SignalType::Terminate:
process->terminate(); process->terminate();
break; break;
case StopProcessPacket::SignalType::Kill: case ControlProcessPacket::SignalType::Kill:
process->kill(); process->kill();
break; break;
case StopProcessPacket::SignalType::Close: case ControlProcessPacket::SignalType::Close:
removeProcess(process->token()); removeProcess(process->token());
break; break;
case ControlProcessPacket::SignalType::CloseWriteChannel:
process->closeWriteChannel();
break;
} }
} }

View File

@@ -39,7 +39,7 @@ private:
void handleStartPacket(); void handleStartPacket();
void handleWritePacket(); void handleWritePacket();
void handleStopPacket(); void handleControlPacket();
void handleShutdownPacket(); void handleShutdownPacket();
void sendPacket(const LauncherPacket &packet); void sendPacket(const LauncherPacket &packet);