diff --git a/src/libs/utils/processinterface.cpp b/src/libs/utils/processinterface.cpp index a5e60c97a31..a2dc746905c 100644 --- a/src/libs/utils/processinterface.cpp +++ b/src/libs/utils/processinterface.cpp @@ -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; } diff --git a/src/libs/utils/terminalinterface.cpp b/src/libs/utils/terminalinterface.cpp index 58d48cb910a..74831723296 100644 --- a/src/libs/utils/terminalinterface.cpp +++ b/src/libs/utils/terminalinterface.cpp @@ -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; diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index fa66c344492..b7ff64ab9e3 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -164,7 +164,6 @@ public: const std::optional &env = std::nullopt, const std::optional &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 &env, const std::optional &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; } diff --git a/src/tools/process_stub/main.cpp b/src/tools/process_stub/main.cpp index 45ac9c41f9b..3a3dd8af33b 100644 --- a/src/tools/process_stub/main.cpp +++ b/src/tools/process_stub/main.cpp @@ -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);