From 535d312e935369512f9be3c27b4980b48520cfb7 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 6 Aug 2021 14:43:03 +0200 Subject: [PATCH] Implement writing to process inside process launcher Change-Id: I7321a941024d431cc52b3f6ae0b1ef38d851db8c Reviewed-by: hjk --- src/libs/utils/launcherpackets.cpp | 9 +++++++ src/libs/utils/launcherpackets.h | 13 ++++++++++ src/libs/utils/launchersocket.cpp | 12 ++++++++++ src/libs/utils/launchersocket.h | 2 ++ src/libs/utils/qtcprocess.cpp | 2 +- .../processlauncher/launchersockethandler.cpp | 24 ++++++++++++++++++- .../processlauncher/launchersockethandler.h | 1 + 7 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/libs/utils/launcherpackets.cpp b/src/libs/utils/launcherpackets.cpp index c971f1494ba..a830c92fb2c 100644 --- a/src/libs/utils/launcherpackets.cpp +++ b/src/libs/utils/launcherpackets.cpp @@ -98,6 +98,15 @@ void StopProcessPacket::doDeserialize(QDataStream &stream) Q_UNUSED(stream); } +void WritePacket::doSerialize(QDataStream &stream) const +{ + stream << inputData; +} + +void WritePacket::doDeserialize(QDataStream &stream) +{ + stream >> inputData; +} ProcessErrorPacket::ProcessErrorPacket(quintptr token) : LauncherPacket(LauncherPacketType::ProcessError, token) diff --git a/src/libs/utils/launcherpackets.h b/src/libs/utils/launcherpackets.h index 27ce9d2cc4d..1eb2e98403d 100644 --- a/src/libs/utils/launcherpackets.h +++ b/src/libs/utils/launcherpackets.h @@ -40,6 +40,7 @@ enum class LauncherPacketType { // client -> launcher packets: Shutdown, StartProcess, + WriteIntoProcess, StopProcess, // launcher -> client packets: ProcessError, @@ -139,6 +140,18 @@ private: 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 { public: diff --git a/src/libs/utils/launchersocket.cpp b/src/libs/utils/launchersocket.cpp index 914357e3a48..73bc6a6f0c6 100644 --- a/src/libs/utils/launchersocket.cpp +++ b/src/libs/utils/launchersocket.cpp @@ -333,6 +333,18 @@ void LauncherHandle::start(const QString &program, const QStringList &arguments, 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 void LauncherHandle::createCallerHandle() { diff --git a/src/libs/utils/launchersocket.h b/src/libs/utils/launchersocket.h index 5440971963d..476e7583568 100644 --- a/src/libs/utils/launchersocket.h +++ b/src/libs/utils/launchersocket.h @@ -89,6 +89,8 @@ public: // Who should remove this object? deleteLater()? 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; } QString program() const { QMutexLocker locker(&m_mutex); return m_command; } void setStandardInputFile(const QString &fileName) { QMutexLocker locker(&m_mutex); m_standardInputFile = fileName; } diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index ebce712ed01..ddf8d7fc758 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -306,7 +306,7 @@ public: void terminate() override { cancel(); } // TODO: what are differences among terminate, kill and close? void kill() 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 setStandardInputFile(const QString &fileName) override { m_handle->setStandardInputFile(fileName); } diff --git a/src/tools/processlauncher/launchersockethandler.cpp b/src/tools/processlauncher/launchersockethandler.cpp index 4cac175edb4..6af02211417 100644 --- a/src/tools/processlauncher/launchersockethandler.cpp +++ b/src/tools/processlauncher/launchersockethandler.cpp @@ -132,6 +132,9 @@ void LauncherSocketHandler::handleSocketData() case LauncherPacketType::StartProcess: handleStartPacket(); break; + case LauncherPacketType::WriteIntoProcess: + handleWritePacket(); + break; case LauncherPacketType::StopProcess: handleStopPacket(); break; @@ -235,7 +238,26 @@ void LauncherSocketHandler::handleStartPacket() process->setProcessChannelMode(packet.channelMode); process->setStandardInputFile(packet.standardInputFile); process->start(packet.command, packet.arguments, packet.openMode); - process->closeWriteChannel(); + const bool shouldCloseWriteChannel = !(packet.openMode & QIODevice::WriteOnly); + if (shouldCloseWriteChannel) + 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( + m_packetParser.token(), + m_packetParser.packetData()); + process->write(packet.inputData); } void LauncherSocketHandler::handleStopPacket() diff --git a/src/tools/processlauncher/launchersockethandler.h b/src/tools/processlauncher/launchersockethandler.h index 1b17f387e1f..cfd65b36e17 100644 --- a/src/tools/processlauncher/launchersockethandler.h +++ b/src/tools/processlauncher/launchersockethandler.h @@ -59,6 +59,7 @@ private: void handleProcessFinished(); void handleStartPacket(); + void handleWritePacket(); void handleStopPacket(); void handleShutdownPacket();