Commit 1c1c6dd1 authored by Arjen Hiemstra's avatar Arjen Hiemstra
Browse files

Lookup CGroup PIDs in a separate thread

This prevents reading the cgroup files from blocking the main thread.
parent 6dbd0444
......@@ -26,6 +26,7 @@
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QStringView>
#include <QThreadPool>
#include "process.h"
......@@ -95,21 +96,24 @@ void CGroup::setProcesses(QVector<Process *> procs)
d->procs = procs;
}
QVector<pid_t> KSysGuard::CGroup::getPids() const
void KSysGuard::CGroup::requestPids(std::function<void (const QVector<pid_t>&)> callback)
{
const QString pidFilePath = cgroupSysBasePath() + d->processGroupId + QLatin1String("/cgroup.procs");
QFile pidFile(pidFilePath);
pidFile.open(QFile::ReadOnly | QIODevice::Text);
QTextStream stream(&pidFile);
QVector<pid_t> procs;
QString line = stream.readLine();
while (!line.isNull()) {
procs.append(line.toLong());
line = stream.readLine();
}
QString path = cgroupSysBasePath() + d->processGroupId + QLatin1String("/cgroup.procs");
auto runnable = [path, callback]() {
QFile pidFile(path);
pidFile.open(QFile::ReadOnly | QIODevice::Text);
QTextStream stream(&pidFile);
QVector<pid_t> pids;
QString line = stream.readLine();
while (!line.isNull()) {
pids.append(line.toLong());
line = stream.readLine();
}
return procs;
callback(pids);
};
QThreadPool::globalInstance()->start(runnable);
}
QString CGroupPrivate::unescapeName(const QString &name) {
......
......@@ -58,14 +58,18 @@ public:
* @return A Vector of pids
* @note This reloads the data on every fetch
*/
QVector<pid_t> getPids() const;
QVector<Process*> processes() const;
/**
* @brief updates and fetches the list of processes associated with the process
* @return A Vector of pids
* @note This reloads the data on every fetch
* Request fetching the list of processes associated with this cgroup.
*
* This is done in a separate thread. Once it has completed, \p callback is
* called with the list of pids of this cgroup.
*
* \param callback A callback that gets called once the list of pids has
* been retrieved.
*/
QVector<Process*> processes() const;
void requestPids(std::function<void(const QVector<pid_t>&)> callback);
/**
* Returns the base path to exposed cgroup information. Either /sys/fs/cgroup or /sys/fs/cgroup/unified as applicable
......
......@@ -399,15 +399,24 @@ void CGroupDataModel::update(CGroup *node)
// Update our own stat info
// This may trigger some dataChanged
const QVector<pid_t> pids = node->getPids();
QVector<Process*> processes;
for (const pid_t pid : pids) {
auto proc = d->m_processes->getProcess(pid);
if (proc) { // as potentially this is racey with when kprocess fetched data
processes << proc;
}
}
node->setProcesses(processes);
node->requestPids([this, node](const QVector<pid_t> pids) {
// The callback is called from a different thread, to avoid needing to
// make the entire thing thread safe, we do the actual data update on the
// main thread.
QMetaObject::invokeMethod(this, [this, node, pids]() {
QVector<Process*> processes;
for (const pid_t pid : pids) {
auto proc = d->m_processes->getProcess(pid);
if (proc) { // as potentially this is racey with when kprocess fetched data
processes << proc;
}
}
node->setProcesses(processes);
auto row = d->m_cGroups.indexOf(node);
Q_EMIT dataChanged(index(row, 0, QModelIndex()), index(row, 0, QModelIndex()),{ ProcessDataModel::PIDs });
}, Qt::QueuedConnection);
});
const auto entries = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
for (auto subDir : entries) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment