From fb6fc2bde8c3202a43dee2d2b1b101a29229f0e5 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Tue, 31 Jan 2023 09:21:39 +0100 Subject: [PATCH] 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: Reviewed-by: hjk --- src/libs/utils/environment.h | 4 ++++ src/libs/utils/qtcprocess.cpp | 10 +++++----- src/plugins/remotelinux/linuxdevice.cpp | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h index 795f65e2e4b..3e53c7a3c51 100644 --- a/src/libs/utils/environment.h +++ b/src/libs/utils/environment.h @@ -81,6 +81,9 @@ public: 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 + 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 constEnd() const { return m_dict.constEnd(); } // FIXME: avoid const_iterator constFind(const QString &name) const { return m_dict.constFind(name); } // FIXME: avoid @@ -102,6 +105,7 @@ public: private: NameValueDictionary m_dict; + bool m_combineWithDeviceEnvironment = true; }; class QTCREATOR_UTILS_EXPORT EnvironmentChange final diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 92717a571bb..80017038b63 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -670,11 +670,11 @@ public: Environment fullEnvironment() const { Environment env = m_setup.m_environment; - if (!env.hasChanges()) { -// FIXME: Either switch to using EnvironmentChange instead of full Environments, or -// feed the full environment into the QtcProcess instead of fixing it up here. -// qWarning("QtcProcess::start: Empty environment set when running '%s'.", -// qPrintable(m_setup.m_commandLine.executable().toString())); + if (!env.hasChanges() && env.combineWithDeviceEnvironment()) { + // FIXME: Either switch to using EnvironmentChange instead of full Environments, or + // feed the full environment into the QtcProcess instead of fixing it up here. + // qWarning("QtcProcess::start: Empty environment set when running '%s'.", + // qPrintable(m_setup.m_commandLine.executable().toString())); env = m_setup.m_commandLine.executable().deviceEnvironment(); } // TODO: needs SshSettings diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 465c03ed974..95275ba282e 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -359,6 +359,8 @@ public: RunResult runInShell(const CommandLine &cmdLine, const QByteArray &stdInData) const override; + Environment deviceEnvironment() const override; + LinuxDevicePrivate *m_dev; }; @@ -388,6 +390,19 @@ RunResult LinuxDeviceFileAccess::runInShell(const CommandLine &cmdLine, 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 class SshProcessInterfacePrivate : public QObject