Utils: Send __qtc marker from stub

Docker and ssh devices need the real process id on the
remote device. The process stub now send this if it receives
it as the first line of output.

Change-Id: I5d3af39651958fc88d21c3854a0fa1d7f51547a6
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Marcus Tillmanns
2023-03-24 09:26:42 +01:00
parent 242d19c19d
commit f1f5a7412a
4 changed files with 68 additions and 19 deletions

View File

@@ -29,8 +29,10 @@ int ProcessInterface::controlSignalToInt(ControlSignal controlSignal)
case ControlSignal::Terminate: return 15;
case ControlSignal::Kill: return 9;
case ControlSignal::Interrupt: return 2;
case ControlSignal::KickOff: QTC_CHECK(false); return 0;
case ControlSignal::CloseWriteChannel: QTC_CHECK(false); return 0;
case ControlSignal::KickOff: return 19;
case ControlSignal::CloseWriteChannel:
QTC_CHECK(false);
return 0;
}
return 0;
}

View File

@@ -183,6 +183,8 @@ void TerminalInterface::onStubReadyRead()
emitFinished(out.mid(5).toInt(), QProcess::NormalExit);
} else if (out.startsWith("crash ")) {
emitFinished(out.mid(6).toInt(), QProcess::CrashExit);
} else if (out.startsWith("qtc: ")) {
emit readyRead(out.mid(5) + "\n", {});
} else {
emitError(QProcess::UnknownError, msgUnexpectedOutput(out));
break;

View File

@@ -164,7 +164,6 @@ public:
const std::optional<Environment> &env = std::nullopt,
const std::optional<FilePath> &workDir = std::nullopt,
bool interactive = false,
bool includeMarker = true,
bool withPty = false);
bool prepareForBuild(const Target *target);
@@ -315,16 +314,17 @@ void DockerProcessImpl::start()
if (m_setup.m_lowPriority)
m_process.setLowPriority();
const bool inTerminal = m_setup.m_terminalMode != TerminalMode::Off;
const bool interactive = m_setup.m_processMode == ProcessMode::Writer
|| !m_setup.m_writeData.isEmpty();
|| !m_setup.m_writeData.isEmpty() || inTerminal;
const CommandLine fullCommandLine
= m_devicePrivate->withDockerExecCmd(m_setup.m_commandLine,
m_setup.m_environment,
m_setup.m_workingDirectory,
interactive,
true,
m_setup.m_ptyData.has_value());
inTerminal);
m_process.setCommand(fullCommandLine);
m_process.start();
@@ -472,7 +472,6 @@ CommandLine DockerDevicePrivate::withDockerExecCmd(const CommandLine &cmd,
const std::optional<Environment> &env,
const std::optional<FilePath> &workDir,
bool interactive,
bool includeMarker,
bool withPty)
{
if (!m_settings)
@@ -501,20 +500,16 @@ CommandLine DockerDevicePrivate::withDockerExecCmd(const CommandLine &cmd,
dockerCmd.addArg(m_container);
if (includeMarker) {
dockerCmd.addArgs({"/bin/sh", "-c"});
dockerCmd.addArgs({"/bin/sh", "-c"});
CommandLine exec("exec");
exec.addCommandLineAsArgs(cmd, CommandLine::Raw);
CommandLine exec("exec");
exec.addCommandLineAsArgs(cmd, CommandLine::Raw);
CommandLine echo("echo");
echo.addArgs("__qtc$$qtc__", CommandLine::Raw);
echo.addCommandLineWithAnd(exec);
CommandLine echo("echo");
echo.addArgs("__qtc$$qtc__", CommandLine::Raw);
echo.addCommandLineWithAnd(exec);
dockerCmd.addCommandLineAsSingleArg(echo);
} else {
dockerCmd.addCommandLineAsArgs(cmd, CommandLine::Raw);
}
dockerCmd.addCommandLineAsSingleArg(echo);
return dockerCmd;
}

View File

@@ -137,6 +137,11 @@ void sendMsg(const QByteArray &msg)
}
}
void sendQtcMarker(const QByteArray &marker)
{
sendMsg(QByteArray("qtc: ") + marker + "\n");
}
void sendPid(int inferiorPid)
{
sendMsg(QString("pid %1\n").arg(inferiorPid).toUtf8());
@@ -273,6 +278,26 @@ void setupPidPollTimer()
pollPidTimer.start();
#endif
}
enum class Out { StdOut, StdErr };
void writeToOut(const QByteArray &data, Out out)
{
#ifdef Q_OS_WIN
static const HANDLE outHandle = GetStdHandle(STD_OUTPUT_HANDLE);
static const HANDLE errHandle = GetStdHandle(STD_ERROR_HANDLE);
WriteFile(out == Out::StdOut ? outHandle : errHandle,
data.constData(),
data.size(),
nullptr,
nullptr);
#else
auto fp = out == Out::StdOut ? stdout : stderr;
::fwrite(data.constData(), 1, data.size(), fp);
::fflush(fp);
#endif
}
void startProcess(const QString &executable, const QStringList &arguments, const QString &workingDir)
{
setupPidPollTimer();
@@ -292,7 +317,32 @@ void startProcess(const QString &executable, const QStringList &arguments, const
QCoreApplication::instance(),
&onInferiorStarted);
inferiorProcess.setProcessChannelMode(QProcess::ForwardedChannels);
inferiorProcess.setProcessChannelMode(QProcess::SeparateChannels);
QObject::connect(&inferiorProcess,
&QProcess::readyReadStandardOutput,
QCoreApplication::instance(),
[] {
const QByteArray data = inferiorProcess.readAllStandardOutput();
static bool isFirst = true;
if (isFirst) {
isFirst = false;
if (data.startsWith("__qtc")) {
int lineBreak = data.indexOf("\r\n");
sendQtcMarker(data.mid(0, lineBreak));
if (lineBreak != -1)
writeToOut(data.mid(lineBreak + 2), Out::StdOut);
return;
}
}
writeToOut(data, Out::StdOut);
});
QObject::connect(&inferiorProcess,
&QProcess::readyReadStandardError,
QCoreApplication::instance(),
[] { writeToOut(inferiorProcess.readAllStandardOutput(), Out::StdErr); });
if (!(testMode && debugMode))
inferiorProcess.setInputChannelMode(QProcess::ForwardedInputChannel);
inferiorProcess.setWorkingDirectory(workingDir);