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)
|
ProcessFinishedPacket::ProcessFinishedPacket(quintptr token)
|
||||||
: LauncherPacket(LauncherPacketType::ProcessFinished, token)
|
: LauncherPacket(LauncherPacketType::ProcessFinished, token)
|
||||||
{
|
{
|
||||||
|
@@ -37,7 +37,16 @@ namespace Utils {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
enum class LauncherPacketType {
|
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
|
class PacketParser
|
||||||
@@ -153,6 +162,33 @@ private:
|
|||||||
void doDeserialize(QDataStream &stream) override;
|
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
|
class ProcessFinishedPacket : public LauncherPacket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -103,6 +103,12 @@ void LauncherHandle::handlePacket(LauncherPacketType type, const QByteArray &pay
|
|||||||
case LauncherPacketType::ProcessStarted:
|
case LauncherPacketType::ProcessStarted:
|
||||||
handleStartedPacket(payload);
|
handleStartedPacket(payload);
|
||||||
break;
|
break;
|
||||||
|
case LauncherPacketType::ReadyReadStandardOutput:
|
||||||
|
handleReadyReadStandardOutput(payload);
|
||||||
|
break;
|
||||||
|
case LauncherPacketType::ReadyReadStandardError:
|
||||||
|
handleReadyReadStandardError(payload);
|
||||||
|
break;
|
||||||
case LauncherPacketType::ProcessFinished:
|
case LauncherPacketType::ProcessFinished:
|
||||||
handleFinishedPacket(payload);
|
handleFinishedPacket(payload);
|
||||||
break;
|
break;
|
||||||
@@ -165,10 +171,47 @@ void LauncherHandle::handleStartedPacket(const QByteArray &packetData)
|
|||||||
m_processState = QProcess::Running;
|
m_processState = QProcess::Running;
|
||||||
const auto packet = LauncherPacket::extractPacket<ProcessStartedPacket>(m_token, packetData);
|
const auto packet = LauncherPacket::extractPacket<ProcessStartedPacket>(m_token, packetData);
|
||||||
m_processId = packet.processId;
|
m_processId = packet.processId;
|
||||||
if (m_callerHandle) {
|
if (!m_callerHandle)
|
||||||
m_callerHandle->appendSignal(SignalType::Started);
|
return;
|
||||||
flushCaller();
|
|
||||||
}
|
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)
|
void LauncherHandle::handleFinishedPacket(const QByteArray &packetData)
|
||||||
@@ -180,16 +223,17 @@ void LauncherHandle::handleFinishedPacket(const QByteArray &packetData)
|
|||||||
m_processState = QProcess::NotRunning;
|
m_processState = QProcess::NotRunning;
|
||||||
const auto packet = LauncherPacket::extractPacket<ProcessFinishedPacket>(m_token, packetData);
|
const auto packet = LauncherPacket::extractPacket<ProcessFinishedPacket>(m_token, packetData);
|
||||||
m_exitCode = packet.exitCode;
|
m_exitCode = packet.exitCode;
|
||||||
m_stdout = packet.stdOut;
|
m_stdout += packet.stdOut;
|
||||||
m_stderr = packet.stdErr;
|
m_stderr += packet.stdErr;
|
||||||
m_errorString = packet.errorString;
|
m_errorString = packet.errorString;
|
||||||
m_exitStatus = packet.exitStatus;
|
m_exitStatus = packet.exitStatus;
|
||||||
if (m_callerHandle) {
|
if (!m_callerHandle)
|
||||||
if (!m_stdout.isEmpty() || !m_stderr.isEmpty())
|
return;
|
||||||
m_callerHandle->appendSignal(SignalType::ReadyRead);
|
|
||||||
m_callerHandle->appendSignal(SignalType::Finished);
|
if (!m_stdout.isEmpty() || !m_stderr.isEmpty())
|
||||||
flushCaller();
|
m_callerHandle->appendSignal(SignalType::ReadyRead);
|
||||||
}
|
m_callerHandle->appendSignal(SignalType::Finished);
|
||||||
|
flushCaller();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherHandle::handleSocketReady()
|
void LauncherHandle::handleSocketReady()
|
||||||
@@ -476,6 +520,8 @@ void LauncherSocket::handleSocketDataAvailable()
|
|||||||
switch (m_packetParser.type()) {
|
switch (m_packetParser.type()) {
|
||||||
case LauncherPacketType::ProcessError:
|
case LauncherPacketType::ProcessError:
|
||||||
case LauncherPacketType::ProcessStarted:
|
case LauncherPacketType::ProcessStarted:
|
||||||
|
case LauncherPacketType::ReadyReadStandardOutput:
|
||||||
|
case LauncherPacketType::ReadyReadStandardError:
|
||||||
case LauncherPacketType::ProcessFinished:
|
case LauncherPacketType::ProcessFinished:
|
||||||
handle->handlePacket(m_packetParser.type(), m_packetParser.packetData());
|
handle->handlePacket(m_packetParser.type(), m_packetParser.packetData());
|
||||||
break;
|
break;
|
||||||
|
@@ -139,6 +139,8 @@ private:
|
|||||||
void handlePacket(LauncherPacketType type, const QByteArray &payload);
|
void handlePacket(LauncherPacketType type, const QByteArray &payload);
|
||||||
void handleErrorPacket(const QByteArray &packetData);
|
void handleErrorPacket(const QByteArray &packetData);
|
||||||
void handleStartedPacket(const QByteArray &packetData);
|
void handleStartedPacket(const QByteArray &packetData);
|
||||||
|
void handleReadyReadStandardOutput(const QByteArray &packetData);
|
||||||
|
void handleReadyReadStandardError(const QByteArray &packetData);
|
||||||
void handleFinishedPacket(const QByteArray &packetData);
|
void handleFinishedPacket(const QByteArray &packetData);
|
||||||
|
|
||||||
void handleSocketReady();
|
void handleSocketReady();
|
||||||
|
@@ -332,7 +332,7 @@ public:
|
|||||||
void setErrorString(const QString &str) override { m_handle->setErrorString(str); }
|
void setErrorString(const QString &str) override { m_handle->setErrorString(str); }
|
||||||
|
|
||||||
bool waitForStarted(int msecs) override { return m_handle->waitForStarted(msecs); }
|
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); }
|
bool waitForFinished(int msecs) override { return m_handle->waitForFinished(msecs); }
|
||||||
|
|
||||||
void setLowPriority() override { QTC_CHECK(false); }
|
void setLowPriority() override { QTC_CHECK(false); }
|
||||||
|
@@ -186,6 +186,22 @@ void LauncherSocketHandler::handleProcessStarted()
|
|||||||
sendPacket(packet);
|
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()
|
void LauncherSocketHandler::handleProcessFinished()
|
||||||
{
|
{
|
||||||
Process * proc = senderProcess();
|
Process * proc = senderProcess();
|
||||||
@@ -276,6 +292,10 @@ Process *LauncherSocketHandler::setupProcess(quintptr token)
|
|||||||
const auto p = new Process(token, this);
|
const auto p = new Process(token, this);
|
||||||
connect(p, &QProcess::errorOccurred, this, &LauncherSocketHandler::handleProcessError);
|
connect(p, &QProcess::errorOccurred, this, &LauncherSocketHandler::handleProcessError);
|
||||||
connect(p, &QProcess::started, this, &LauncherSocketHandler::handleProcessStarted);
|
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),
|
connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||||
this, &LauncherSocketHandler::handleProcessFinished);
|
this, &LauncherSocketHandler::handleProcessFinished);
|
||||||
connect(p, &Process::failedToStop, this, &LauncherSocketHandler::handleStopFailure);
|
connect(p, &Process::failedToStop, this, &LauncherSocketHandler::handleStopFailure);
|
||||||
|
@@ -54,6 +54,8 @@ private:
|
|||||||
void handleSocketClosed();
|
void handleSocketClosed();
|
||||||
void handleProcessError();
|
void handleProcessError();
|
||||||
void handleProcessStarted();
|
void handleProcessStarted();
|
||||||
|
void handleReadyReadStandardOutput();
|
||||||
|
void handleReadyReadStandardError();
|
||||||
void handleProcessFinished();
|
void handleProcessFinished();
|
||||||
void handleStopFailure();
|
void handleStopFailure();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user