forked from qt-creator/qt-creator
LinuxDevice: Get rid of a marker for outputForRunInShell()
Don't rely on a synthetic marker when running a shell command and expecting any output. The marker might always be a part of the output data from the running command. That's unreliable. A solution is to do a similar thing that we are doing inside runInShell(). We ignore the error channel there, so it means that when calling outputForRunInShell() we have two channels for our purposes. So, the output from the command we pass through, and its error channel we redirect to /dev/null. Later, we run "echo $?", which prints the return code from the last command and we redirect it to standard error channel. Inside outputForRunInShell() we read the error channel as long as we detect something there. We assert if it's being convertible to int and we also assert that the command itself succeeded. Afterwards we break the endless loop and read the output channel for the first time - it should contain all the output gathered from the running command. Change-Id: Ia0ad73623f813ef593c11dff9bdba4df9e524315 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -57,6 +57,7 @@
|
|||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QScopeGuard>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
@@ -233,6 +234,7 @@ public:
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(m_shell, return false);
|
QTC_ASSERT(m_shell, return false);
|
||||||
QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs
|
QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs
|
||||||
|
QTC_CHECK(m_shell->readAllStandardError().isNull()); // clean possible left-overs
|
||||||
|
|
||||||
const QByteArray prefix = !data.isEmpty()
|
const QByteArray prefix = !data.isEmpty()
|
||||||
? QByteArray("echo '" + data.toBase64() + "' | base64 -d | ") : QByteArray("");
|
? QByteArray("echo '" + data.toBase64() + "' | base64 -d | ") : QByteArray("");
|
||||||
@@ -255,26 +257,29 @@ public:
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(m_shell, return {});
|
QTC_ASSERT(m_shell, return {});
|
||||||
QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs
|
QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs
|
||||||
|
QTC_CHECK(m_shell->readAllStandardError().isNull()); // clean possible left-overs
|
||||||
|
auto cleanup = qScopeGuard([this] { m_shell->readAllStandardOutput(); }); // clean on assert
|
||||||
|
|
||||||
static int val = 0;
|
const QByteArray suffix = QByteArray(" 2> /dev/null \necho $? 1>&2\n");
|
||||||
const QByteArray delim = QString::number(++val, 16).toUtf8();
|
const QByteArray command = cmd.toUtf8() + suffix;
|
||||||
|
|
||||||
DEBUG("RUN2 " << cmd);
|
m_shell->write(command);
|
||||||
const QByteArray marker = "___QTC___" + delim + "_OUTPUT_MARKER___";
|
DEBUG("RUN2 " << cmd.toUserOutput());
|
||||||
DEBUG(" CMD: " << cmd.toUtf8() + "\necho " + marker + "\n");
|
|
||||||
m_shell->write(cmd.toUtf8() + "\necho " + marker + "\n");
|
while (true) {
|
||||||
QByteArray output;
|
|
||||||
while (!output.contains(marker)) {
|
|
||||||
DEBUG("OUTPUT" << output);
|
|
||||||
m_shell->waitForReadyRead();
|
m_shell->waitForReadyRead();
|
||||||
output.append(m_shell->readAllStandardOutput());
|
const QByteArray error = m_shell->readAllStandardError();
|
||||||
|
if (!error.isNull()) {
|
||||||
|
bool ok = false;
|
||||||
|
const int result = error.toInt(&ok);
|
||||||
|
QTC_ASSERT(ok, return {});
|
||||||
|
QTC_ASSERT(!result, return {});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
const QByteArray output = m_shell->readAllStandardOutput();
|
||||||
DEBUG("GOT2 " << output);
|
DEBUG("GOT2 " << output);
|
||||||
LOG("Run command in shell:" << cmd << "output size:" << output.size());
|
LOG("Run command in shell:" << cmd << "output size:" << output.size());
|
||||||
const int pos = output.indexOf(marker);
|
|
||||||
if (pos >= 0)
|
|
||||||
output = output.left(pos);
|
|
||||||
DEBUG("CHOPPED2 " << output);
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user