forked from qt-creator/qt-creator
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:
@@ -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);
|
||||||
|
@@ -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()
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user