Process: Use GeneralProcessBlockingImpl for QProcess implementation

This should fix the Process::waitForReadyRead() when the data
appeared on stdErr channel and not on stdOut channel.

Amends ec722b9132

Change-Id: Ib9f361f4d1602487bdbbb735e55d0ad24fb5e4c3
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Jarek Kobus
2023-12-06 17:44:50 +01:00
parent db4486e915
commit a737ddd931
3 changed files with 32 additions and 26 deletions

View File

@@ -163,8 +163,6 @@ CommandLine DeviceShell::createFallbackCommand(const CommandLine &cmd)
expected_str<void> DeviceShell::start() expected_str<void> DeviceShell::start()
{ {
m_shellProcess = std::make_unique<Process>(); m_shellProcess = std::make_unique<Process>();
// FIXME: This shouldn't be needed, it's a temporary workaround.
m_shellProcess->setProcessImpl(ProcessImpl::ProcessLauncher);
connect(m_shellProcess.get(), &Process::done, m_shellProcess.get(), connect(m_shellProcess.get(), &Process::done, m_shellProcess.get(),
[this] { emit done(m_shellProcess->resultData()); }); [this] { emit done(m_shellProcess->resultData()); });
connect(&m_thread, &QThread::finished, m_shellProcess.get(), [this] { closeShellProcess(); }, Qt::DirectConnection); connect(&m_thread, &QThread::finished, m_shellProcess.get(), [this] { closeShellProcess(); }, Qt::DirectConnection);

View File

@@ -292,27 +292,37 @@ bool DefaultImpl::ensureProgramExists(const QString &program)
return false; return false;
} }
class QProcessBlockingImpl : public ProcessBlockingInterface // TODO: Remove QProcessBlockingImpl later, after Creator 13.0 is released at least.
{
public:
QProcessBlockingImpl(QProcess *process) : m_process(process) {}
private: // Rationale: QProcess::waitForReadyRead() waits only for one channel, either stdOut or stdErr.
bool waitForSignal(ProcessSignalType signalType, int msecs) final // Since we can't predict where the data will come first,
{ // setting the QProcess::setReadChannel() in advance is a mis-design of the QProcess API.
switch (signalType) { // This issue does not affect GeneralProcessBlockingImpl, but it might be not as optimal
case ProcessSignalType::Started: // as QProcessBlockingImpl. However, since we are blocking the caller thread anyway,
return m_process->waitForStarted(msecs); // the small overhead in speed doesn't play the most significant role, thus the proper
case ProcessSignalType::ReadyRead: // behavior of Process::waitForReadyRead(), which listens to both channels, wins.
return m_process->waitForReadyRead(msecs);
case ProcessSignalType::Done:
return m_process->waitForFinished(msecs);
}
return false;
}
QProcess *m_process = nullptr; // class QProcessBlockingImpl : public ProcessBlockingInterface
}; // {
// public:
// QProcessBlockingImpl(QProcess *process) : m_process(process) {}
// private:
// bool waitForSignal(ProcessSignalType signalType, int msecs) final
// {
// switch (signalType) {
// case ProcessSignalType::Started:
// return m_process->waitForStarted(msecs);
// case ProcessSignalType::ReadyRead:
// return m_process->waitForReadyRead(msecs);
// case ProcessSignalType::Done:
// return m_process->waitForFinished(msecs);
// }
// return false;
// }
// QProcess *m_process = nullptr;
// };
class PtyProcessImpl final : public DefaultImpl class PtyProcessImpl final : public DefaultImpl
{ {
@@ -445,7 +455,7 @@ class QProcessImpl final : public DefaultImpl
public: public:
QProcessImpl() QProcessImpl()
: m_process(new ProcessHelper(this)) : m_process(new ProcessHelper(this))
, m_blockingImpl(new QProcessBlockingImpl(m_process)) // , m_blockingImpl(new QProcessBlockingImpl(m_process))
{ {
connect(m_process, &QProcess::started, this, &QProcessImpl::handleStarted); connect(m_process, &QProcess::started, this, &QProcessImpl::handleStarted);
connect(m_process, &QProcess::finished, this, &QProcessImpl::handleFinished); connect(m_process, &QProcess::finished, this, &QProcessImpl::handleFinished);
@@ -481,7 +491,7 @@ private:
} }
} }
ProcessBlockingInterface *processBlockingInterface() const override { return m_blockingImpl; } // ProcessBlockingInterface *processBlockingInterface() const override { return m_blockingImpl; }
void doDefaultStart(const QString &program, const QStringList &arguments) final void doDefaultStart(const QString &program, const QStringList &arguments) final
{ {
@@ -533,7 +543,7 @@ private:
} }
ProcessHelper *m_process = nullptr; ProcessHelper *m_process = nullptr;
QProcessBlockingImpl *m_blockingImpl = nullptr; // QProcessBlockingImpl *m_blockingImpl = nullptr;
}; };
static uint uniqueToken() static uint uniqueToken()

View File

@@ -272,8 +272,6 @@ void tst_Process::multiRead()
Process process; Process process;
subConfig.setupSubProcess(&process); subConfig.setupSubProcess(&process);
// TODO: Fix ProcessImpl::QProcess
process.setProcessImpl(ProcessImpl::ProcessLauncher);
process.setProcessMode(ProcessMode::Writer); process.setProcessMode(ProcessMode::Writer);
process.start(); process.start();