Utils: Add combine with device env option

Adds the option Environment::combineWithDeviceEnvironment. This allows
the linuxdevice to set it to false.

Without this option a deadlock would occur when the QtcProcess tries to
get the device environment and the device shell failed to start.
(e.g. because a required command is missing on the device).

Change-Id: I8f7550d0d90e989a339f27e993a836e67e910e33
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Marcus Tillmanns
2023-01-31 09:21:39 +01:00
parent cf692bd2f6
commit fb6fc2bde8
3 changed files with 24 additions and 5 deletions

View File

@@ -81,6 +81,9 @@ public:
QString value(const_iterator it) const { return m_dict.value(it); } // FIXME: avoid QString value(const_iterator it) const { return m_dict.value(it); } // FIXME: avoid
bool isEnabled(const_iterator it) const { return m_dict.isEnabled(it); } // FIXME: avoid bool isEnabled(const_iterator it) const { return m_dict.isEnabled(it); } // FIXME: avoid
void setCombineWithDeviceEnvironment(bool combine) { m_combineWithDeviceEnvironment = combine; }
bool combineWithDeviceEnvironment() const { return m_combineWithDeviceEnvironment; }
const_iterator constBegin() const { return m_dict.constBegin(); } // FIXME: avoid const_iterator constBegin() const { return m_dict.constBegin(); } // FIXME: avoid
const_iterator constEnd() const { return m_dict.constEnd(); } // FIXME: avoid const_iterator constEnd() const { return m_dict.constEnd(); } // FIXME: avoid
const_iterator constFind(const QString &name) const { return m_dict.constFind(name); } // FIXME: avoid const_iterator constFind(const QString &name) const { return m_dict.constFind(name); } // FIXME: avoid
@@ -102,6 +105,7 @@ public:
private: private:
NameValueDictionary m_dict; NameValueDictionary m_dict;
bool m_combineWithDeviceEnvironment = true;
}; };
class QTCREATOR_UTILS_EXPORT EnvironmentChange final class QTCREATOR_UTILS_EXPORT EnvironmentChange final

View File

@@ -670,11 +670,11 @@ public:
Environment fullEnvironment() const Environment fullEnvironment() const
{ {
Environment env = m_setup.m_environment; Environment env = m_setup.m_environment;
if (!env.hasChanges()) { if (!env.hasChanges() && env.combineWithDeviceEnvironment()) {
// FIXME: Either switch to using EnvironmentChange instead of full Environments, or // FIXME: Either switch to using EnvironmentChange instead of full Environments, or
// feed the full environment into the QtcProcess instead of fixing it up here. // feed the full environment into the QtcProcess instead of fixing it up here.
// qWarning("QtcProcess::start: Empty environment set when running '%s'.", // qWarning("QtcProcess::start: Empty environment set when running '%s'.",
// qPrintable(m_setup.m_commandLine.executable().toString())); // qPrintable(m_setup.m_commandLine.executable().toString()));
env = m_setup.m_commandLine.executable().deviceEnvironment(); env = m_setup.m_commandLine.executable().deviceEnvironment();
} }
// TODO: needs SshSettings // TODO: needs SshSettings

View File

@@ -359,6 +359,8 @@ public:
RunResult runInShell(const CommandLine &cmdLine, RunResult runInShell(const CommandLine &cmdLine,
const QByteArray &stdInData) const override; const QByteArray &stdInData) const override;
Environment deviceEnvironment() const override;
LinuxDevicePrivate *m_dev; LinuxDevicePrivate *m_dev;
}; };
@@ -388,6 +390,19 @@ RunResult LinuxDeviceFileAccess::runInShell(const CommandLine &cmdLine,
return m_dev->runInShell(cmdLine, stdInData); return m_dev->runInShell(cmdLine, stdInData);
} }
Environment LinuxDeviceFileAccess::deviceEnvironment() const
{
QtcProcess getEnvProc;
getEnvProc.setCommand({FilePath("env").onDevice(m_dev->q->rootPath()), {}});
Environment inEnv;
inEnv.setCombineWithDeviceEnvironment(false);
getEnvProc.setEnvironment(inEnv);
getEnvProc.runBlocking();
const QString remoteOutput = getEnvProc.cleanedStdOut();
return Environment(remoteOutput.split('\n', Qt::SkipEmptyParts), m_dev->q->osType());
}
// SshProcessImpl // SshProcessImpl
class SshProcessInterfacePrivate : public QObject class SshProcessInterfacePrivate : public QObject