From 1b501420533a3e58d74d24dfd33d81f8b02e0808 Mon Sep 17 00:00:00 2001 From: Theodore Wang Date: Tue, 12 Sep 2023 20:31:13 +0800 Subject: [PATCH] Calls ProcessInfo::readArguments periodically on ProcessInfo::update When ssh is run via 'exec ssh [ssh arguments]', ProcessInfo::_arguments is not updated since ProcessInfo::readArguments is only called once when the process is started. Thus, SSHProcessInfo::SSHProcessInfo will have soft errors since it relies heavily on reading ProcessInfo::_arguments which are outdated. A solution is to call ProcessInfo::clearArguments followed by ProcessInfo::readArguments whenever ProcessInfo::update is called if there is a change in process name. --- src/NullProcessInfo.cpp | 5 +++++ src/NullProcessInfo.h | 1 + src/ProcessInfo.cpp | 39 ++++++++------------------------------- src/ProcessInfo.h | 8 ++++++++ src/UnixProcessInfo.cpp | 26 ++++++++++++++++++++++++++ src/UnixProcessInfo.h | 9 ++------- 6 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/NullProcessInfo.cpp b/src/NullProcessInfo.cpp index 9229ee283..b39c0982f 100644 --- a/src/NullProcessInfo.cpp +++ b/src/NullProcessInfo.cpp @@ -27,6 +27,11 @@ bool NullProcessInfo::readCurrentDir(int /*pid*/) return false; } +bool NullProcessInfo::readArguments(int /*pid*/) +{ + return false; +} + void NullProcessInfo::readUserName() { } diff --git a/src/NullProcessInfo.h b/src/NullProcessInfo.h index caa367fc7..9c082045f 100644 --- a/src/NullProcessInfo.h +++ b/src/NullProcessInfo.h @@ -31,6 +31,7 @@ protected: void readProcessInfo(int pid) override; bool readProcessName(int pid) override; bool readCurrentDir(int pid) override; + bool readArguments(int pid) override; void readUserName(void) override; }; diff --git a/src/ProcessInfo.cpp b/src/ProcessInfo.cpp index c07bcaedc..1e5cb8c9b 100644 --- a/src/ProcessInfo.cpp +++ b/src/ProcessInfo.cpp @@ -98,8 +98,16 @@ void ProcessInfo::setError(Error error) void ProcessInfo::update() { + bool ok; + const QString oldName(name(&ok)); + readCurrentDir(_pid); readProcessName(_pid); + + if (ok && oldName != name(&ok) && ok) { + clearArguments(); + readArguments(_pid); + } } QString ProcessInfo::validCurrentDir() const @@ -597,31 +605,6 @@ private: return ok; } - bool readArguments(int pid) override - { - // read command-line arguments file found at /proc//cmdline - // the expected format is a list of strings delimited by null characters, - // and ending in a double null character pair. - - QFile argumentsFile(QStringLiteral("/proc/%1/cmdline").arg(pid)); - if (argumentsFile.open(QIODevice::ReadOnly)) { - QTextStream stream(&argumentsFile); - const QString &data = stream.readAll(); - - const QStringList &argList = data.split(QLatin1Char('\0')); - - for (const QString &entry : argList) { - if (!entry.isEmpty()) { - addArgument(entry); - } - } - } else { - setFileError(argumentsFile.error()); - } - - return true; - } - QDBusMessage callSmdDBus(const QString &objectPath, const QString &interfaceName, const QString &methodName, const QList &args) { const QString service(QStringLiteral("org.freedesktop.systemd1")); @@ -1274,12 +1257,6 @@ private: return true; } - bool readArguments(int /*pid*/) override - { - // Handled in readProcInfo() - return false; - } - std::unique_ptr _execNameFile; }; #endif diff --git a/src/ProcessInfo.h b/src/ProcessInfo.h index 2360dbdcd..ab4f33896 100644 --- a/src/ProcessInfo.h +++ b/src/ProcessInfo.h @@ -224,6 +224,14 @@ protected: */ virtual bool readCurrentDir(int pid) = 0; + /** + * Determine what arguments were passed to the process. + * Sets _arguments. + * @param pid process ID to use + * @return true on success + */ + virtual bool readArguments(int pid) = 0; + /* Read the user name */ virtual void readUserName(void) = 0; diff --git a/src/UnixProcessInfo.cpp b/src/UnixProcessInfo.cpp index c9daaf679..080c6e6b1 100644 --- a/src/UnixProcessInfo.cpp +++ b/src/UnixProcessInfo.cpp @@ -91,6 +91,32 @@ void UnixProcessInfo::readUserName() delete[] getpwBuffer; } +bool UnixProcessInfo::readArguments(int pid) +{ + // used for LinuxProcessInfo and SolarisProcessInfo + // read command-line arguments file found at /proc//cmdline + // the expected format is a list of strings delimited by null characters, + // and ending in a double null character pair. + + QFile argumentsFile(QStringLiteral("/proc/%1/cmdline").arg(pid)); + if (argumentsFile.open(QIODevice::ReadOnly)) { + QTextStream stream(&argumentsFile); + const QString &data = stream.readAll(); + + const QStringList &argList = data.split(QLatin1Char('\0')); + + for (const QString &entry : argList) { + if (!entry.isEmpty()) { + addArgument(entry); + } + } + } else { + setFileError(argumentsFile.error()); + } + + return true; +} + #if defined(Q_OS_FREEBSD) || defined(Q_OS_OPEN_BSD) || defined(Q_OS_MACOS) QSharedPointer UnixProcessInfo::getProcInfoStruct(int *managementInfoBase, int mibCount) { diff --git a/src/UnixProcessInfo.h b/src/UnixProcessInfo.h index 2a6726df9..26ec0f734 100644 --- a/src/UnixProcessInfo.h +++ b/src/UnixProcessInfo.h @@ -42,6 +42,8 @@ protected: void readUserName(void) override; + bool readArguments(int pid) override; + #if defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) /** * Allocates an array of struct kinfo_proc and calls sysctl internally to fill it up @@ -59,13 +61,6 @@ private: * @return true on success */ virtual bool readProcInfo(int pid) = 0; - - /** - * Determine what arguments were passed to the process. Sets _arguments. - * @param pid process ID to use - * @return true on success - */ - virtual bool readArguments(int pid) = 0; }; #endif }