forked from qt-creator/qt-creator
Implement readyRead inside process launcher
Change-Id: I3a27edef2307053b8c4c7d8f1dbf7e0400e27416 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -118,6 +118,17 @@ void ProcessErrorPacket::doDeserialize(QDataStream &stream)
|
||||
}
|
||||
|
||||
|
||||
void ReadyReadPacket::doSerialize(QDataStream &stream) const
|
||||
{
|
||||
stream << standardChannel;
|
||||
}
|
||||
|
||||
void ReadyReadPacket::doDeserialize(QDataStream &stream)
|
||||
{
|
||||
stream >> standardChannel;
|
||||
}
|
||||
|
||||
|
||||
ProcessFinishedPacket::ProcessFinishedPacket(quintptr token)
|
||||
: LauncherPacket(LauncherPacketType::ProcessFinished, token)
|
||||
{
|
||||
|
@@ -37,7 +37,16 @@ namespace Utils {
|
||||
namespace Internal {
|
||||
|
||||
enum class LauncherPacketType {
|
||||
Shutdown, StartProcess, ProcessStarted, StopProcess, ProcessError, ProcessFinished
|
||||
// client -> launcher packets:
|
||||
Shutdown,
|
||||
StartProcess,
|
||||
StopProcess,
|
||||
// launcher -> client packets:
|
||||
ProcessError,
|
||||
ProcessStarted,
|
||||
ReadyReadStandardOutput,
|
||||
ReadyReadStandardError,
|
||||
ProcessFinished
|
||||
};
|
||||
|
||||
class PacketParser
|
||||
@@ -153,6 +162,33 @@ private:
|
||||
void doDeserialize(QDataStream &stream) override;
|
||||
};
|
||||
|
||||
class ReadyReadPacket : public LauncherPacket
|
||||
{
|
||||
public:
|
||||
QByteArray standardChannel;
|
||||
|
||||
protected:
|
||||
ReadyReadPacket(LauncherPacketType type, quintptr token) : LauncherPacket(type, token) { }
|
||||
|
||||
private:
|
||||
void doSerialize(QDataStream &stream) const override;
|
||||
void doDeserialize(QDataStream &stream) override;
|
||||
};
|
||||
|
||||
class ReadyReadStandardOutputPacket : public ReadyReadPacket
|
||||
{
|
||||
public:
|
||||
ReadyReadStandardOutputPacket(quintptr token)
|
||||
: ReadyReadPacket(LauncherPacketType::ReadyReadStandardOutput, token) { }
|
||||
};
|
||||
|
||||
class ReadyReadStandardErrorPacket : public ReadyReadPacket
|
||||
{
|
||||
public:
|
||||
ReadyReadStandardErrorPacket(quintptr token)
|
||||
: ReadyReadPacket(LauncherPacketType::ReadyReadStandardError, token) { }
|
||||
};
|
||||
|
||||
class ProcessFinishedPacket : public LauncherPacket
|
||||
{
|
||||
public:
|
||||
|
@@ -103,6 +103,12 @@ void LauncherHandle::handlePacket(LauncherPacketType type, const QByteArray &pay
|
||||
case LauncherPacketType::ProcessStarted:
|
||||
handleStartedPacket(payload);
|
||||
break;
|
||||
case LauncherPacketType::ReadyReadStandardOutput:
|
||||
handleReadyReadStandardOutput(payload);
|
||||
break;
|
||||
case LauncherPacketType::ReadyReadStandardError:
|
||||
handleReadyReadStandardError(payload);
|
||||
break;
|
||||
case LauncherPacketType::ProcessFinished:
|
||||
handleFinishedPacket(payload);
|
||||
break;
|
||||
@@ -165,10 +171,47 @@ void LauncherHandle::handleStartedPacket(const QByteArray &packetData)
|
||||
m_processState = QProcess::Running;
|
||||
const auto packet = LauncherPacket::extractPacket<ProcessStartedPacket>(m_token, packetData);
|
||||
m_processId = packet.processId;
|
||||
if (m_callerHandle) {
|
||||
m_callerHandle->appendSignal(SignalType::Started);
|
||||
flushCaller();
|
||||
}
|
||||
if (!m_callerHandle)
|
||||
return;
|
||||
|
||||
m_callerHandle->appendSignal(SignalType::Started);
|
||||
flushCaller();
|
||||
}
|
||||
|
||||
void LauncherHandle::handleReadyReadStandardOutput(const QByteArray &packetData)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
wakeUpIfWaitingFor(SignalType::ReadyRead);
|
||||
if (m_canceled)
|
||||
return;
|
||||
const auto packet = LauncherPacket::extractPacket<ReadyReadStandardOutputPacket>(m_token, packetData);
|
||||
if (packet.standardChannel.isEmpty())
|
||||
return;
|
||||
|
||||
m_stdout += packet.standardChannel;
|
||||
if (!m_callerHandle)
|
||||
return;
|
||||
|
||||
m_callerHandle->appendSignal(SignalType::ReadyRead);
|
||||
flushCaller();
|
||||
}
|
||||
|
||||
void LauncherHandle::handleReadyReadStandardError(const QByteArray &packetData)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
wakeUpIfWaitingFor(SignalType::ReadyRead);
|
||||
if (m_canceled)
|
||||
return;
|
||||
const auto packet = LauncherPacket::extractPacket<ReadyReadStandardErrorPacket>(m_token, packetData);
|
||||
if (packet.standardChannel.isEmpty())
|
||||
return;
|
||||
|
||||
m_stderr += packet.standardChannel;
|
||||
if (!m_callerHandle)
|
||||
return;
|
||||
|
||||
m_callerHandle->appendSignal(SignalType::ReadyRead);
|
||||
flushCaller();
|
||||
}
|
||||
|
||||
void LauncherHandle::handleFinishedPacket(const QByteArray &packetData)
|
||||
@@ -180,16 +223,17 @@ void LauncherHandle::handleFinishedPacket(const QByteArray &packetData)
|
||||
m_processState = QProcess::NotRunning;
|
||||
const auto packet = LauncherPacket::extractPacket<ProcessFinishedPacket>(m_token, packetData);
|
||||
m_exitCode = packet.exitCode;
|
||||
m_stdout = packet.stdOut;
|
||||
m_stderr = packet.stdErr;
|
||||
m_stdout += packet.stdOut;
|
||||
m_stderr += packet.stdErr;
|
||||
m_errorString = packet.errorString;
|
||||
m_exitStatus = packet.exitStatus;
|
||||
if (m_callerHandle) {
|
||||
if (!m_stdout.isEmpty() || !m_stderr.isEmpty())
|
||||
m_callerHandle->appendSignal(SignalType::ReadyRead);
|
||||
m_callerHandle->appendSignal(SignalType::Finished);
|
||||
flushCaller();
|
||||
}
|
||||
if (!m_callerHandle)
|
||||
return;
|
||||
|
||||
if (!m_stdout.isEmpty() || !m_stderr.isEmpty())
|
||||
m_callerHandle->appendSignal(SignalType::ReadyRead);
|
||||
m_callerHandle->appendSignal(SignalType::Finished);
|
||||
flushCaller();
|
||||
}
|
||||
|
||||
void LauncherHandle::handleSocketReady()
|
||||
@@ -476,6 +520,8 @@ void LauncherSocket::handleSocketDataAvailable()
|
||||
switch (m_packetParser.type()) {
|
||||
case LauncherPacketType::ProcessError:
|
||||
case LauncherPacketType::ProcessStarted:
|
||||
case LauncherPacketType::ReadyReadStandardOutput:
|
||||
case LauncherPacketType::ReadyReadStandardError:
|
||||
case LauncherPacketType::ProcessFinished:
|
||||
handle->handlePacket(m_packetParser.type(), m_packetParser.packetData());
|
||||
break;
|
||||
|
@@ -139,6 +139,8 @@ private:
|
||||
void handlePacket(LauncherPacketType type, const QByteArray &payload);
|
||||
void handleErrorPacket(const QByteArray &packetData);
|
||||
void handleStartedPacket(const QByteArray &packetData);
|
||||
void handleReadyReadStandardOutput(const QByteArray &packetData);
|
||||
void handleReadyReadStandardError(const QByteArray &packetData);
|
||||
void handleFinishedPacket(const QByteArray &packetData);
|
||||
|
||||
void handleSocketReady();
|
||||
|
@@ -332,7 +332,7 @@ public:
|
||||
void setErrorString(const QString &str) override { m_handle->setErrorString(str); }
|
||||
|
||||
bool waitForStarted(int msecs) override { return m_handle->waitForStarted(msecs); }
|
||||
bool waitForReadyRead(int msecs) override { QTC_CHECK(false); return false; }
|
||||
bool waitForReadyRead(int msecs) override { return m_handle->waitForReadyRead(msecs); }
|
||||
bool waitForFinished(int msecs) override { return m_handle->waitForFinished(msecs); }
|
||||
|
||||
void setLowPriority() override { QTC_CHECK(false); }
|
||||
|
@@ -186,6 +186,22 @@ void LauncherSocketHandler::handleProcessStarted()
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
void LauncherSocketHandler::handleReadyReadStandardOutput()
|
||||
{
|
||||
Process * proc = senderProcess();
|
||||
ReadyReadStandardOutputPacket packet(proc->token());
|
||||
packet.standardChannel = proc->readAllStandardOutput();
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
void LauncherSocketHandler::handleReadyReadStandardError()
|
||||
{
|
||||
Process * proc = senderProcess();
|
||||
ReadyReadStandardErrorPacket packet(proc->token());
|
||||
packet.standardChannel = proc->readAllStandardError();
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
void LauncherSocketHandler::handleProcessFinished()
|
||||
{
|
||||
Process * proc = senderProcess();
|
||||
@@ -276,6 +292,10 @@ Process *LauncherSocketHandler::setupProcess(quintptr token)
|
||||
const auto p = new Process(token, this);
|
||||
connect(p, &QProcess::errorOccurred, this, &LauncherSocketHandler::handleProcessError);
|
||||
connect(p, &QProcess::started, this, &LauncherSocketHandler::handleProcessStarted);
|
||||
connect(p, &QProcess::readyReadStandardOutput,
|
||||
this, &LauncherSocketHandler::handleReadyReadStandardOutput);
|
||||
connect(p, &QProcess::readyReadStandardError,
|
||||
this, &LauncherSocketHandler::handleReadyReadStandardError);
|
||||
connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||
this, &LauncherSocketHandler::handleProcessFinished);
|
||||
connect(p, &Process::failedToStop, this, &LauncherSocketHandler::handleStopFailure);
|
||||
|
@@ -54,6 +54,8 @@ private:
|
||||
void handleSocketClosed();
|
||||
void handleProcessError();
|
||||
void handleProcessStarted();
|
||||
void handleReadyReadStandardOutput();
|
||||
void handleReadyReadStandardError();
|
||||
void handleProcessFinished();
|
||||
void handleStopFailure();
|
||||
|
||||
|
Reference in New Issue
Block a user