mirror of
https://invent.kde.org/marcoa/a-la-karte.git
synced 2026-03-26 17:03:08 +00:00
Harden systemd scope cleanup
Tighten transient unit lifecycle handling in GameCenter. - Drop stale unit watcher mappings on PropertiesChanged for removed sessions. - When stopping a monitored launch due to timeout or attach failure, fall back to terminating scope PIDs if StopUnit fails unexpectedly. This reduces leaked scopes and improves robustness in failure paths.
This commit is contained in:
parent
985f6dac03
commit
7200ad179c
1 changed files with 53 additions and 4 deletions
|
|
@ -833,6 +833,15 @@ void GameCenterDaemon::handleSystemdUnitPropertiesChanged(const QDBusObjectPath
|
|||
|
||||
auto sit = m_sessions.find(sessionId);
|
||||
if (sit == m_sessions.end()) {
|
||||
unwatchSystemdUnit({}, unitPath);
|
||||
|
||||
for (auto nameIt = m_unitNameToSessionId.begin(); nameIt != m_unitNameToSessionId.end();) {
|
||||
if (nameIt.value() == sessionId) {
|
||||
nameIt = m_unitNameToSessionId.erase(nameIt);
|
||||
} else {
|
||||
++nameIt;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1570,8 +1579,31 @@ QString GameCenterDaemon::launchMonitored(const QVariantMap &launchSpec, const Q
|
|||
QVariantMap finalState = sessionToVariantMap(it.value(), stopping ? QStringLiteral("Stopped") : QStringLiteral("Failed"));
|
||||
|
||||
if (!it.value().unitName.isEmpty()) {
|
||||
m_systemd.stopUnit(it.value().unitName);
|
||||
unwatchSystemdUnit(it.value().unitName, it.value().unitPath);
|
||||
const QString unitName = it.value().unitName;
|
||||
const QDBusObjectPath unitPath = it.value().unitPath;
|
||||
const uint mainPid = it.value().mainPid;
|
||||
|
||||
const QDBusReply<QDBusObjectPath> stopReply = m_systemd.stopUnit(unitName);
|
||||
if (!stopReply.isValid() && stopReply.error().name() != QLatin1String("org.freedesktop.systemd1.NoSuchUnit")) {
|
||||
QList<uint> pids;
|
||||
if (!unitPath.path().isEmpty()) {
|
||||
pids = m_systemd.scopePids(unitPath);
|
||||
}
|
||||
if (pids.isEmpty() && it.value().process && it.value().process->processId() > 0) {
|
||||
pids = {static_cast<uint>(it.value().process->processId())};
|
||||
}
|
||||
if (pids.isEmpty() && mainPid > 0) {
|
||||
pids = {mainPid};
|
||||
}
|
||||
if (!pids.isEmpty()) {
|
||||
terminatePids(pids);
|
||||
QTimer::singleShot(5000, this, [pids]() {
|
||||
killPids(pids);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
unwatchSystemdUnit(unitName, unitPath);
|
||||
}
|
||||
|
||||
if (it.value().scanner) {
|
||||
|
|
@ -1643,8 +1675,25 @@ void GameCenterDaemon::attachPidsToSession(const QString &sessionId, const QList
|
|||
};
|
||||
|
||||
if (!it.value().unitName.isEmpty()) {
|
||||
m_systemd.stopUnit(it.value().unitName);
|
||||
unwatchSystemdUnit(it.value().unitName, it.value().unitPath);
|
||||
const QString staleUnitName = it.value().unitName;
|
||||
const QDBusObjectPath staleUnitPath = it.value().unitPath;
|
||||
|
||||
const QDBusReply<QDBusObjectPath> stopReply = m_systemd.stopUnit(staleUnitName);
|
||||
if (!stopReply.isValid() && stopReply.error().name() != QLatin1String("org.freedesktop.systemd1.NoSuchUnit")) {
|
||||
QList<uint> stalePids;
|
||||
if (!staleUnitPath.path().isEmpty()) {
|
||||
stalePids = m_systemd.scopePids(staleUnitPath);
|
||||
}
|
||||
if (stalePids.isEmpty()) {
|
||||
stalePids = pids;
|
||||
}
|
||||
terminatePids(stalePids);
|
||||
QTimer::singleShot(5000, this, [stalePids]() {
|
||||
killPids(stalePids);
|
||||
});
|
||||
}
|
||||
|
||||
unwatchSystemdUnit(staleUnitName, staleUnitPath);
|
||||
}
|
||||
|
||||
QVariantMap finalState = sessionToVariantMap(it.value(), QStringLiteral("Failed"));
|
||||
|
|
|
|||
Loading…
Reference in a new issue