From ffa9d02d483573e2c4157bd79c12ecbc9b6691f2 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 3 Mar 2024 15:23:41 -0800 Subject: [PATCH] feat(process): add ways to close stdio channels --- src/io/process.cpp | 29 +++++++++++++++++++++++++++++ src/io/process.hpp | 16 +++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/io/process.cpp b/src/io/process.cpp index dfa8051..416147c 100644 --- a/src/io/process.cpp +++ b/src/io/process.cpp @@ -41,6 +41,12 @@ void Process::setStdoutParser(DataStreamParser* parser) { if (this->mStdoutParser != nullptr) { QObject::disconnect(this->mStdoutParser, nullptr, this, nullptr); + + if (this->process != nullptr) { + this->process->closeReadChannel(QProcess::StandardOutput); + this->process->readAllStandardOutput(); // discard + this->stdoutBuffer.clear(); + } } this->mStdoutParser = parser; @@ -68,6 +74,12 @@ void Process::setStderrParser(DataStreamParser* parser) { if (this->mStderrParser != nullptr) { QObject::disconnect(this->mStderrParser, nullptr, this, nullptr); + + if (this->process != nullptr) { + this->process->closeReadChannel(QProcess::StandardError); + this->process->readAllStandardError(); // discard + this->stderrBuffer.clear(); + } } this->mStderrParser = parser; @@ -88,6 +100,19 @@ void Process::onStderrParserDestroyed() { emit this->stderrParserChanged(); } +bool Process::stdinEnabled() const { return this->mStdinEnabled; } + +void Process::setStdinEnabled(bool enabled) { + if (enabled == this->mStdinEnabled) return; + this->mStdinEnabled = enabled; + + if (!enabled && this->process != nullptr) { + this->process->closeWriteChannel(); + } + + emit this->stdinEnabledChanged(); +} + void Process::startProcessIfReady() { if (this->process != nullptr || !this->targetRunning || this->mCommand.isEmpty()) return; this->targetRunning = false; @@ -108,6 +133,10 @@ void Process::startProcessIfReady() { this->stdoutBuffer.clear(); this->stderrBuffer.clear(); + if (this->mStdoutParser == nullptr) this->process->closeReadChannel(QProcess::StandardOutput); + if (this->mStderrParser == nullptr) this->process->closeReadChannel(QProcess::StandardError); + if (!this->mStdinEnabled) this->process->closeWriteChannel(); + this->process->start(cmd, args); } diff --git a/src/io/process.hpp b/src/io/process.hpp index 9801931..95d0241 100644 --- a/src/io/process.hpp +++ b/src/io/process.hpp @@ -51,10 +51,15 @@ class Process: public QObject { /// > [!INFO] You can use `["sh", "-c", ]` to execute your command with /// > the system shell. Q_PROPERTY(QList command READ command WRITE setCommand NOTIFY commandChanged); - /// The parser for STDOUT. If the parser is null no data will be read. + /// The parser for stdout. If the parser is null the process's stdout channel will be closed + /// and no further data will be read, even if a new parser is attached. Q_PROPERTY(DataStreamParser* stdout READ stdoutParser WRITE setStdoutParser NOTIFY stdoutParserChanged); - /// The parser for STDERR. If the parser is null no data will be read. + /// The parser for stderr. If the parser is null the process's stdout channel will be closed + /// and no further data will be read, even if a new parser is attached. Q_PROPERTY(DataStreamParser* stderr READ stderrParser WRITE setStderrParser NOTIFY stderrParserChanged); + /// If stdin is enabled. Defaults to true. If this property is set to false the process's stdin channel + /// will be closed and [write](#func.write) will do nothing, even if set back to true. + Q_PROPERTY(bool stdinEnabled READ stdinEnabled WRITE setStdinEnabled NOTIFY stdinEnabledChanged); // clang-format on QML_ELEMENT; @@ -64,7 +69,7 @@ public: /// Sends a signal to the process if `running` is true, otherwise does nothing. Q_INVOKABLE void signal(qint32 signal); - /// Writes to the process's STDIN. Does nothing if `running` is false. + /// Writes to the process's stdin. Does nothing if `running` is false. Q_INVOKABLE void write(const QString& data); [[nodiscard]] bool isRunning() const; @@ -81,6 +86,9 @@ public: [[nodiscard]] DataStreamParser* stderrParser() const; void setStderrParser(DataStreamParser* parser); + [[nodiscard]] bool stdinEnabled() const; + void setStdinEnabled(bool enabled); + signals: void started(); void exited(qint32 exitCode, QProcess::ExitStatus exitStatus); @@ -90,6 +98,7 @@ signals: void commandChanged(); void stdoutParserChanged(); void stderrParserChanged(); + void stdinEnabledChanged(); private slots: void onStarted(); @@ -111,4 +120,5 @@ private: QByteArray stderrBuffer; bool targetRunning = false; + bool mStdinEnabled = false; };