nandi/memwatchpublic Fork 0
df1c928
Commits
Clone
git clone https://git.rickub.com/nandi/memwatch.git
git clone ssh://git@rickub.com/nandi/memwatch.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

oomd drop-in: arm user@.service, not user.slice

oomd kills a descendant of what it monitors, choosing among that
cgroup's children. Armed on user.slice the only candidate is
user-$UID.slice -- the entire login session, compositor included -- so
the backstop's kill action was "log the user out" rather than "kill the
hog". Move it to user@.service, where the candidates are app.slice,
session.slice and background.slice.

This is the same trap as the session-3.scope victim that eligible_cgroup()
exists to block; it just arrived via a different mechanism.

Applied and verified: oomctl shows user@1000.service monitored at 60%
over oomd's 20s window, with app.slice and descendants as candidates.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandithebull committed 2026-09-20T16:45:34-07:00 Browse files
df1c928 parent: 937fc8b
modified optional/10-user-pressure.conf +10 -3
@@ -1,12 +1,19 @@
1-# Drop-in for user.slice: /etc/systemd/system/user.slice.d/10-user-pressure.conf
1+# Drop-in for user@.service: /etc/systemd/system/user@.service.d/10-user-pressure.conf
22 #
33 # Out of the box user.slice has ManagedOOMMemoryPressure=auto, which inherits
44 # from the root slice, which is off. The result is that systemd-oomd watches
55 # system.slice and completely ignores every application you actually run.
66 #
7-# This arms it at 60% pressure sustained over oomd's default 30s window. It is
7+# This arms it at 60% pressure sustained over oomd's default 20s window. It is
88 # deliberately slower and dumber than memwatchd -- it is the backstop for the
99 # case where memwatchd is dead, wedged, or wrong. It kills without asking.
10-[Slice]
10+#
11+# Note the placement. oomd kills a *descendant* of what it monitors, picking
12+# among that cgroup's children. Armed on user.slice, the only candidate is
13+# user-$UID.slice -- the whole login session, compositor included, so firing
14+# means a logout. Armed here on user@.service the candidates are app.slice,
15+# session.slice and background.slice, so it takes out applications and leaves
16+# the session standing. Same reasoning as eligible_cgroup() in memwatchd.
17+[Service]
1118 ManagedOOMMemoryPressure=kill
1219 ManagedOOMMemoryPressureLimit=60%
@@ -1,12 +1,19 @@
1-# Drop-in for user.slice: /etc/systemd/system/user.slice.d/10-user-pressure.conf1+# Drop-in for user@.service: /etc/systemd/system/user@.service.d/10-user-pressure.conf
2 #2 #
3 # Out of the box user.slice has ManagedOOMMemoryPressure=auto, which inherits3 # Out of the box user.slice has ManagedOOMMemoryPressure=auto, which inherits
4 # from the root slice, which is off. The result is that systemd-oomd watches4 # from the root slice, which is off. The result is that systemd-oomd watches
5 # system.slice and completely ignores every application you actually run.5 # system.slice and completely ignores every application you actually run.
6 #6 #
7-# This arms it at 60% pressure sustained over oomd's default 30s window. It is7+# This arms it at 60% pressure sustained over oomd's default 20s window. It is
8 # deliberately slower and dumber than memwatchd -- it is the backstop for the8 # deliberately slower and dumber than memwatchd -- it is the backstop for the
9 # case where memwatchd is dead, wedged, or wrong. It kills without asking.9 # case where memwatchd is dead, wedged, or wrong. It kills without asking.
10-[Slice]10+#
11+# Note the placement. oomd kills a *descendant* of what it monitors, picking
12+# among that cgroup's children. Armed on user.slice, the only candidate is
13+# user-$UID.slice -- the whole login session, compositor included, so firing
14+# means a logout. Armed here on user@.service the candidates are app.slice,
15+# session.slice and background.slice, so it takes out applications and leaves
16+# the session standing. Same reasoning as eligible_cgroup() in memwatchd.
17+[Service]
11 ManagedOOMMemoryPressure=kill18 ManagedOOMMemoryPressure=kill
12 ManagedOOMMemoryPressureLimit=60%19 ManagedOOMMemoryPressureLimit=60%