diff options
author | Robert Adam <dev@robert-adam.de> | 2021-05-09 21:22:04 +0300 |
---|---|---|
committer | Robert Adam <dev@robert-adam.de> | 2021-05-10 15:50:51 +0300 |
commit | 5d56ec6889f82bfa863ea97fe3ab20fbf52c5bf8 (patch) | |
tree | dc7e53eec85f6abd075e50ddf07e1e4324ca36bd /src | |
parent | f0eee51e8138fa1154262fbca5d55a569539f930 (diff) |
REFAC: ProcessResolver
The new version now uses smart pointers instead of raw new and delete
and also switched to using STL type for its API instead of Qt types.
Diffstat (limited to 'src')
-rw-r--r-- | src/ProcessResolver.cpp | 76 | ||||
-rw-r--r-- | src/ProcessResolver.h | 30 | ||||
-rw-r--r-- | src/mumble/PluginManager.cpp | 18 |
3 files changed, 50 insertions, 74 deletions
diff --git a/src/ProcessResolver.cpp b/src/ProcessResolver.cpp index b303b4eaa..8e4153f9c 100644 --- a/src/ProcessResolver.cpp +++ b/src/ProcessResolver.cpp @@ -6,59 +6,45 @@ #include "ProcessResolver.h" #include <cstring> -ProcessResolver::ProcessResolver(bool resolveImmediately) : m_processNames(), m_processPIDs() { +ProcessResolver::ProcessResolver(bool resolveImmediately) : m_processMap() { if (resolveImmediately) { resolve(); } } ProcessResolver::~ProcessResolver() { - freeAndClearData(); + m_processMap.clear(); } -void ProcessResolver::freeAndClearData() { - // delete all names - for (const char *currentName : m_processNames) { - delete[] currentName; - } - - m_processNames.clear(); - m_processPIDs.clear(); -} - -const QVector< const char * > &ProcessResolver::getProcessNames() const { - return m_processNames; -} - -const QVector< uint64_t > &ProcessResolver::getProcessPIDs() const { - return m_processPIDs; +const ProcessResolver::ProcessMap &ProcessResolver::getProcessMap() const { + return m_processMap; } void ProcessResolver::resolve() { // first clear the current lists - freeAndClearData(); + m_processMap.clear(); doResolve(); } size_t ProcessResolver::amountOfProcesses() const { - return m_processPIDs.size(); + return m_processMap.size(); } -/// Helper function to add a name stored as a stack-variable to the given vector +/// Helper function for adding an entry to the given process map /// -/// @param stackName The pointer to the stack-variable -/// @param destVec The destination vector to add the pointer to -void addName(const char *stackName, QVector< const char * > &destVec) { - // We can't store the pointer of a stack-variable (will be invalid as soon as we exit scope) - // so we'll have to allocate memory on the heap and copy the name there. - size_t nameLength = std::strlen(stackName) + 1; // +1 for terminating NULL-byte - char *name = new char[nameLength]; +/// @param pid The process's PID +/// @param processName The name of the process +/// @param map The map to add the entry to +void addEntry(uint64_t pid, const char *processName, ProcessResolver::ProcessMap &map) { + // In order to make sure the name pointer stays valid until we need it, we have ot copy it + const size_t nameLength = std::strlen(processName) + 1; // +1 for terminating NULL-byte + std::unique_ptr< char[] > nameCopy = std::make_unique< char[] >(nameLength); - std::strcpy(name, stackName); + std::strcpy(nameCopy.get(), processName); - destVec.append(name); + map.insert(std::make_pair(pid, std::move(nameCopy))); } // The implementation of the doResolve-function is platfrom-dependent @@ -113,11 +99,7 @@ void ProcessResolver::doResolve() { while (ok) { if (utf16ToUtf8(pe.szExeFile, sizeof(name), name)) { - // Store name - addName(name, m_processNames); - - // Store corresponding PID - m_processPIDs.append(pe.th32ProcessID); + addEntry(pe.th32ProcessID, name, m_processMap); } # ifndef QT_NO_DEBUG else { @@ -188,11 +170,7 @@ void ProcessResolver::doResolve() { } if (!baseName.isEmpty()) { - // add name - addName(baseName.toUtf8().data(), m_processNames); - - // add corresponding PID - m_processPIDs.append(pid); + addEntry(pid, baseName.toUtf8().constData(), m_processMap); } } } @@ -209,11 +187,7 @@ void ProcessResolver::doResolve() { struct proc_bsdinfo proc; int st = proc_pidinfo(pids[i], PROC_PIDTBSDINFO, 0, &proc, PROC_PIDTBSDINFO_SIZE); if (st == PROC_PIDTBSDINFO_SIZE) { - // add name - addName(proc.pbi_name, m_processNames); - - // add corresponding PID - m_processPIDs.append(pids[i]); + addEntry(pids[i], proc.pbi_name, m_processMap); } } } @@ -234,11 +208,7 @@ void ProcessResolver::doResolve() { } for (int i = 0; i < n_procs; ++i) { - // Add name - addName(procs_info[i].ki_comm, m_processNames); - - // Add corresponding PID - m_processPIDs.append(procs_info[i].ki_pid); + addEntry(procs_info[i].ki_pid, procs_info[i].ki_comm, m_processMap); } free(procs_info); @@ -291,11 +261,7 @@ void ProcessResolver::doResolve() { } for (int i = 0; i < n_procs; ++i) { - // Add name - addName(procs_info[i].ki_comm, m_processNames); - - // Add corresponding PIDs - m_processPIDs.append(procs_info[i].ki_pid); + addEntry(procs_info[i].ki_pid, procs_info[i].ki_comm, m_processMap); } kvm_cleanup(kd); diff --git a/src/ProcessResolver.h b/src/ProcessResolver.h index 6799c0df6..c5c717398 100644 --- a/src/ProcessResolver.h +++ b/src/ProcessResolver.h @@ -9,35 +9,33 @@ #include <QtCore/QVector> #include <cstdint> +#include <memory> +#include <unordered_map> /// This ProcessResolver can be used to get a QVector of running process names and associated PIDs on multiple /// platforms. This object is by no means thread-safe! class ProcessResolver { -protected: - /// The vector for the pointers to the process names - QVector< const char * > m_processNames; - /// The vector for the process PIDs - QVector< uint64_t > m_processPIDs; - - /// Deletes all names currently stored in processNames and clears processNames and processPIDs - void freeAndClearData(); - /// The OS specific implementation of filling in details about running process names and PIDs - void doResolve(); - public: + using ProcessMap = std::unordered_map< uint64_t, std::unique_ptr< char[] > >; + /// @param resolveImmediately Whether the constructor should directly invoke ProcesResolver::resolve() ProcessResolver(bool resolveImmediately = true); virtual ~ProcessResolver(); /// Resolves the namaes and PIDs of the running processes void resolve(); - /// Gets a reference to the stored process names - const QVector< const char * > &getProcessNames() const; - /// Gets a reference to the stored process PIDs (corresponding to the names returned by - /// ProcessResolver::getProcessNames()) - const QVector< uint64_t > &getProcessPIDs() const; + /// @returns The ProcessMap holding the mapping between PID and process name of all processes + /// found by this resolver + const ProcessMap &getProcessMap() const; /// @returns The amount of processes that have been resolved by this object size_t amountOfProcesses() const; + +protected: + /// A map containing the PID->name mapping for the found processes + ProcessMap m_processMap; + + /// The OS specific implementation of filling in details about running process names and PIDs + void doResolve(); }; #endif // MUMBLE_PROCESS_RESOLVER_H_ diff --git a/src/mumble/PluginManager.cpp b/src/mumble/PluginManager.cpp index db7a8dfef..789db6c8a 100644 --- a/src/mumble/PluginManager.cpp +++ b/src/mumble/PluginManager.cpp @@ -29,7 +29,9 @@ #include "ServerHandler.h" #include "Global.h" +#include <cstdint> #include <memory> +#include <vector> #ifdef Q_OS_WIN # include <tlhelp32.h> @@ -199,7 +201,18 @@ bool PluginManager::selectActivePositionalDataPlugin() { return false; } - ProcessResolver procRes(true); + const ProcessResolver procRes(true); + const ProcessResolver::ProcessMap &map = procRes.getProcessMap(); + + // We require 2 separate arrays holding the names and the PIDs -> create them from the given map + std::vector< uint64_t > pids; + std::vector< const char * > names; + pids.reserve(procRes.amountOfProcesses()); + names.reserve(procRes.amountOfProcesses()); + for (const std::pair< const uint64_t, std::unique_ptr< char[] > > ¤tEntry : map) { + pids.push_back(currentEntry.first); + names.push_back(currentEntry.second.get()); + } auto it = m_pluginHashMap.begin(); @@ -209,8 +222,7 @@ bool PluginManager::selectActivePositionalDataPlugin() { plugin_ptr_t currentPlugin = it.value(); if (currentPlugin->isPositionalDataEnabled() && currentPlugin->isLoaded()) { - switch (currentPlugin->initPositionalData(procRes.getProcessNames().data(), procRes.getProcessPIDs().data(), - procRes.amountOfProcesses())) { + switch (currentPlugin->initPositionalData(names.data(), pids.data(), procRes.amountOfProcesses())) { case PDEC_OK: // the plugin is ready to provide positional data m_activePositionalDataPlugin = currentPlugin; |