Fix process info not available in flatpak

Since we are in a sandbox, tcgetpgrp doesn't work. To work around
this limitation, get process info using ps

BUG: 507763
BUG: 508216
This commit is contained in:
Waqar Ahmed
2025-08-31 23:52:24 +05:00
parent 0c426b42d6
commit 62b6f2285e
4 changed files with 149 additions and 6 deletions

View File

@@ -35,6 +35,7 @@
// KDE
#include <KConfigGroup>
#include <KSandbox>
#include <KSharedConfig>
#include <KUser>
@@ -787,6 +788,84 @@ private:
QString LinuxProcessInfo::_createdAppCGroupPath = QString();
bool LinuxProcessInfo::_cGroupCreationFailed = false;
class FlatpakProcessInfo : public ProcessInfo
{
public:
FlatpakProcessInfo(int pid, QByteArrayView tty)
: ProcessInfo(pid)
{
QProcess proc;
proc.setProgram(QStringLiteral("ps"));
proc.setArguments({
QStringLiteral("-o"),
QStringLiteral("%U\t%p\t%c"),
QStringLiteral("--tty"),
QString::fromLatin1(tty.data()),
QStringLiteral("--no-headers"),
});
KSandbox::startHostProcess(proc, QProcess::ReadOnly);
proc.waitForStarted();
proc.waitForFinished();
const QString out = QString::fromUtf8(proc.readAllStandardOutput());
for (QStringView line : QStringTokenizer(out, u'\n', Qt::SkipEmptyParts)) {
using Container = QVarLengthArray<QStringView, 4>;
const Container tokens = QStringTokenizer(line, u'\t', Qt::SkipEmptyParts).toContainer<Container>();
if (tokens[1].toInt() == pid) {
setUserName(tokens[0].trimmed().toString());
setPid(tokens[1].trimmed().toInt());
setName(tokens[2].trimmed().toString());
}
}
}
void readProcessInfo(int) override
{
/* done in ctor */
}
bool readProcessName(int) override
{
return true;
}
bool readCurrentDir(int) override
{
bool ok = false;
QString pidString = QString::number(pid(&ok));
if (!ok) {
return false;
}
QProcess proc;
proc.setProgram(QStringLiteral("pwdx"));
proc.setArguments({pidString});
KSandbox::startHostProcess(proc, QProcess::ReadOnly);
if (proc.waitForStarted() && proc.waitForFinished()) {
proc.setReadChannel(QProcess::StandardOutput);
quint8 buffer[4096];
auto line = proc.readLineInto(buffer).trimmed();
if (int colon = line.indexOf(": "); colon != -1) {
setCurrentDir(QString::fromUtf8(line.mid(colon + 2)));
return true;
}
}
return false;
}
bool readArguments(int) override
{
return false;
}
void readUserName(void) override
{
/* done in ctor */
}
};
#elif defined(Q_OS_FREEBSD)
class FreeBSDProcessInfo : public UnixProcessInfo
{
@@ -1311,11 +1390,19 @@ private:
};
#endif
ProcessInfo *ProcessInfo::newInstance(int pid, int sessionPid)
ProcessInfo *ProcessInfo::newInstance(int pid, int sessionPid, QByteArrayView tty)
{
ProcessInfo *info;
#if defined(Q_OS_LINUX)
info = new LinuxProcessInfo(pid, sessionPid);
if (KSandbox::isFlatpak()) {
if (tty.isEmpty()) {
info = new NullProcessInfo(pid);
} else {
info = new FlatpakProcessInfo(pid, tty);
}
} else {
info = new LinuxProcessInfo(pid, sessionPid);
}
#elif defined(Q_OS_SOLARIS)
info = new SolarisProcessInfo(pid);
#elif defined(Q_OS_MACOS)

View File

@@ -68,8 +68,9 @@ public:
* @param pid The pid of the process to examine
* @param sessionPid -1 if examined process is session process,
* else will be pid of session process of the tab housing examined process
* @param tty the current tty, used by flatpak
*/
static ProcessInfo *newInstance(int pid, int sessionPid = -1);
static ProcessInfo *newInstance(int pid, int sessionPid = -1, QByteArrayView tty = QByteArrayView());
virtual ~ProcessInfo()
{

View File

@@ -23,6 +23,7 @@
// KDE
#include <KPtyDevice>
#include <KSandbox>
using Konsole::Pty;
@@ -303,6 +304,36 @@ void Pty::closePty()
int Pty::foregroundProcessGroup() const
{
if (KSandbox::isFlatpak()) {
QProcess proc;
proc.setProgram(QStringLiteral("ps"));
proc.setArguments({QStringLiteral("-o"),
QStringLiteral("%p\t"),
QStringLiteral("-o"),
QStringLiteral("stat"),
QStringLiteral("-t"),
QStringLiteral("%1").arg(pty()->ttyName()),
QStringLiteral("--no-headers")});
KSandbox::startHostProcess(proc, QProcess::ReadOnly);
if (proc.waitForStarted() && proc.waitForFinished()) {
while (proc.canReadLine()) {
quint8 buffer[256];
const QByteArrayView line = proc.readLineInto(buffer);
int i = line.indexOf('\t');
if (i == -1) {
return 0;
}
QByteArrayView pid = line.mid(0, i);
QByteArrayView stat = line.mid(i + 1);
if (stat.contains("+")) {
return pid.trimmed().toInt();
}
}
}
return 0;
}
const int master_fd = pty()->masterFd();
if (master_fd >= 0) {

View File

@@ -289,7 +289,8 @@ void Session::setInitialWorkingDirectory(const QString &dir)
QString Session::currentWorkingDirectory()
{
if (_reportedWorkingUrl.isValid() && _reportedWorkingUrl.isLocalFile() && (_reportedWorkingUrl.host().length() == 0 || _reportedWorkingUrl.host().compare(QSysInfo::machineHostName(), Qt::CaseInsensitive) == 0)) {
if (_reportedWorkingUrl.isValid() && _reportedWorkingUrl.isLocalFile()
&& (_reportedWorkingUrl.host().length() == 0 || _reportedWorkingUrl.host().compare(QSysInfo::machineHostName(), Qt::CaseInsensitive) == 0)) {
return _reportedWorkingUrl.path();
}
@@ -1224,7 +1225,30 @@ void Session::updateSessionProcessInfo()
// return 0
if ((_sessionProcessInfo == nullptr) || (processId() != 0 && processId() != _sessionProcessInfo->pid(&ok))) {
delete _sessionProcessInfo;
_sessionProcessInfo = ProcessInfo::newInstance(processId());
int sessionPid = processId();
if (KSandbox::isFlatpak()) {
QProcess proc;
proc.setProgram(QStringLiteral("ps"));
proc.setArguments({QStringLiteral("-o"),
QStringLiteral("pid"),
QStringLiteral("-t"),
QStringLiteral("%1").arg(_shellProcess->pty()->ttyName()),
QStringLiteral("--no-headers")});
KSandbox::startHostProcess(proc, QProcess::ReadOnly);
if (proc.waitForStarted() && proc.waitForFinished()) {
proc.setReadChannel(QProcess::StandardOutput);
quint8 buffer[256];
auto line = proc.readLineInto(buffer).trimmed();
bool ok;
auto pid = line.toInt(&ok);
if (ok) {
sessionPid = pid;
}
}
}
_sessionProcessInfo = ProcessInfo::newInstance(sessionPid, -1, _shellProcess->pty()->ttyName());
_sessionProcessInfo->setUserHomeDir();
}
_sessionProcessInfo->update();
@@ -1237,7 +1261,7 @@ bool Session::updateForegroundProcessInfo()
const int foregroundPid = _shellProcess->foregroundProcessGroup();
if (foregroundPid != _foregroundPid) {
delete _foregroundProcessInfo;
_foregroundProcessInfo = ProcessInfo::newInstance(foregroundPid, processId());
_foregroundProcessInfo = ProcessInfo::newInstance(foregroundPid, processId(), _shellProcess->pty()->ttyName());
_foregroundPid = foregroundPid;
}