Implement writing to process inside process launcher

Change-Id: I7321a941024d431cc52b3f6ae0b1ef38d851db8c
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2021-08-06 14:43:03 +02:00
parent 7696f4f37c
commit 535d312e93
7 changed files with 61 additions and 2 deletions

View File

@@ -98,6 +98,15 @@ void StopProcessPacket::doDeserialize(QDataStream &stream)
Q_UNUSED(stream); Q_UNUSED(stream);
} }
void WritePacket::doSerialize(QDataStream &stream) const
{
stream << inputData;
}
void WritePacket::doDeserialize(QDataStream &stream)
{
stream >> inputData;
}
ProcessErrorPacket::ProcessErrorPacket(quintptr token) ProcessErrorPacket::ProcessErrorPacket(quintptr token)
: LauncherPacket(LauncherPacketType::ProcessError, token) : LauncherPacket(LauncherPacketType::ProcessError, token)

View File

@@ -40,6 +40,7 @@ enum class LauncherPacketType {
// client -> launcher packets: // client -> launcher packets:
Shutdown, Shutdown,
StartProcess, StartProcess,
WriteIntoProcess,
StopProcess, StopProcess,
// launcher -> client packets: // launcher -> client packets:
ProcessError, ProcessError,
@@ -139,6 +140,18 @@ private:
void doDeserialize(QDataStream &stream) override; void doDeserialize(QDataStream &stream) override;
}; };
class WritePacket : public LauncherPacket
{
public:
WritePacket(quintptr token) : LauncherPacket(LauncherPacketType::WriteIntoProcess, token) { }
QByteArray inputData;
private:
void doSerialize(QDataStream &stream) const override;
void doDeserialize(QDataStream &stream) override;
};
class ShutdownPacket : public LauncherPacket class ShutdownPacket : public LauncherPacket
{ {
public: public:

View File

@@ -333,6 +333,18 @@ void LauncherHandle::start(const QString &program, const QStringList &arguments,
doStart(); doStart();
} }
qint64 LauncherHandle::write(const QByteArray &data)
{
QMutexLocker locker(&m_mutex);
if (m_processState != QProcess::Running)
return -1;
WritePacket p(m_token);
p.inputData = data;
sendPacket(p);
}
// Ensure it's called from caller's thread, after moving LauncherHandle into the launcher's thread // Ensure it's called from caller's thread, after moving LauncherHandle into the launcher's thread
void LauncherHandle::createCallerHandle() void LauncherHandle::createCallerHandle()
{ {

View File

@@ -89,6 +89,8 @@ public:
// Who should remove this object? deleteLater()? // Who should remove this object? deleteLater()?
void start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode); void start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode);
qint64 write(const QByteArray &data);
QProcess::ProcessError error() const { QMutexLocker locker(&m_mutex); return m_error; } QProcess::ProcessError error() const { QMutexLocker locker(&m_mutex); return m_error; }
QString program() const { QMutexLocker locker(&m_mutex); return m_command; } QString program() const { QMutexLocker locker(&m_mutex); return m_command; }
void setStandardInputFile(const QString &fileName) { QMutexLocker locker(&m_mutex); m_standardInputFile = fileName; } void setStandardInputFile(const QString &fileName) { QMutexLocker locker(&m_mutex); m_standardInputFile = fileName; }

View File

@@ -306,7 +306,7 @@ public:
void terminate() override { cancel(); } // TODO: what are differences among terminate, kill and close? void terminate() override { cancel(); } // TODO: what are differences among terminate, kill and close?
void kill() override { cancel(); } // TODO: see above void kill() override { cancel(); } // TODO: see above
void close() override { cancel(); } // TODO: see above void close() override { cancel(); } // TODO: see above
qint64 write(const QByteArray &data) override { QTC_CHECK(false); return -1; } qint64 write(const QByteArray &data) override { return m_handle->write(data); }
void closeWriteChannel() override { /*QTC_CHECK(false);*/ } void closeWriteChannel() override { /*QTC_CHECK(false);*/ }
void setStandardInputFile(const QString &fileName) override { m_handle->setStandardInputFile(fileName); } void setStandardInputFile(const QString &fileName) override { m_handle->setStandardInputFile(fileName); }

View File

@@ -132,6 +132,9 @@ void LauncherSocketHandler::handleSocketData()
case LauncherPacketType::StartProcess: case LauncherPacketType::StartProcess:
handleStartPacket(); handleStartPacket();
break; break;
case LauncherPacketType::WriteIntoProcess:
handleWritePacket();
break;
case LauncherPacketType::StopProcess: case LauncherPacketType::StopProcess:
handleStopPacket(); handleStopPacket();
break; break;
@@ -235,9 +238,28 @@ void LauncherSocketHandler::handleStartPacket()
process->setProcessChannelMode(packet.channelMode); process->setProcessChannelMode(packet.channelMode);
process->setStandardInputFile(packet.standardInputFile); process->setStandardInputFile(packet.standardInputFile);
process->start(packet.command, packet.arguments, packet.openMode); process->start(packet.command, packet.arguments, packet.openMode);
const bool shouldCloseWriteChannel = !(packet.openMode & QIODevice::WriteOnly);
if (shouldCloseWriteChannel)
process->closeWriteChannel(); process->closeWriteChannel();
} }
void LauncherSocketHandler::handleWritePacket()
{
Process * const process = m_processes.value(m_packetParser.token());
if (!process) {
logWarn("got write request for unknown process");
return;
}
if (process->state() != QProcess::Running) {
logDebug("can't write into not running process");
return;
}
const auto packet = LauncherPacket::extractPacket<WritePacket>(
m_packetParser.token(),
m_packetParser.packetData());
process->write(packet.inputData);
}
void LauncherSocketHandler::handleStopPacket() void LauncherSocketHandler::handleStopPacket()
{ {
Process * const process = m_processes.value(m_packetParser.token()); Process * const process = m_processes.value(m_packetParser.token());

View File

@@ -59,6 +59,7 @@ private:
void handleProcessFinished(); void handleProcessFinished();
void handleStartPacket(); void handleStartPacket();
void handleWritePacket();
void handleStopPacket(); void handleStopPacket();
void handleShutdownPacket(); void handleShutdownPacket();