Skip to content

[Bug]: ManagedOOMPreference=avoid in t3code.service puts systemd --user into a 100% CPU loop with uresourced (Fedora/GNOME) #20931

Open

Description

@tecnobrat

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Fedora 44 Workstation (GNOME), which ships and enables uresourced --user 0.5.4.
  2. Install the background service with a build that includes fix(server): agents run in their own systemd scopes so an OOM kill spares the server #17662 (any nightly since 2026-10-10, or v0.1.0): t3 service install.
  3. Leave it running. At some point (in my case within a day of installing), systemd --user goes to ~100% CPU and stays there.

Expected behavior

The t3code.service unit doesn't cause any ongoing work in the user manager once it's running.

Actual behavior

systemd --user pins a core indefinitely, and uresourced --user sits at ~13–15%. On my machine this has run for about 6 days: the user manager has accumulated 5d18h of CPU time.

The unit template in apps/server/src/cloud/bootService.ts (added in #17662, still on main @ 133f57a) sets ManagedOOMPreference=avoid, and that sets up a feedback loop with uresourced:

  1. Because of ManagedOOMPreference=avoid, systemd sets the user.oomd_avoid xattr on the t3code.service cgroup, and re-applies it whenever the unit's properties change.
  2. Each xattr write is an IN_ATTRIB event on the cgroup directory. uresourced watches app.slice cgroups for IN_ATTRIB and responds with SetUnitProperties(t3code.service, CPUWeight=100, IOWeight=100).
  3. That property change re-applies the xattr, so step 1 happens again, forever.

Measured on a live system:

  • ~2,500 IN_ATTRIB events/sec on app.slice/t3code.service, and zero on any other cgroup in app.slice.
  • ~1,900 SetUnitProperties calls/sec from uresourced --user to the user manager, all for t3code.service, all CPUWeight=100 IOWeight=100.

This is a uresourced bug at heart. It was reported in benzea/uresourced#9, where the reporter also had ManagedOOMPreference=avoid on the affected units, and fixed upstream in b9bf446 (2026-09-20, "avoid reconfiguring units with the same value"). That fix isn't in any tagged release, so Fedora's 0.5.4 still loops. Until distros pick it up, any T3 service install on Fedora/GNOME is exposed.

Side effect: uresourced keeps resetting the weights to 100, so the unit's CPUWeight=1000 / IOWeight=1000 never actually take effect on these systems.

Suggested fix: drop ManagedOOMPreference=avoid from the unit. The comment above it already notes that oomd ignores it on typical distros (oomd watches user-1000.slice, which root owns), and per #17662 the per-agent scopes are what actually protect the server. An alternative is to only emit it when the monitored cgroup is user-owned.

Impact

Major degradation or frequent failure

Version or commit

v0.1.0 (also every nightly since 0.0.46-nightly.20261010); unit template unchanged on main @ 133f57a

Environment

Fedora 44 (kernel 7.2.5-200.fc44), systemd 259.9-1.fc44, uresourced 0.5.4-5.fc44, GNOME on Wayland

Logs or stack traces

$ top -b -n1 -p 1725,1058839
   1725 brian  20   0   28512  15256  10112 R  99.7   0.0   5d+18h systemd
1058839 brian  20   0  382620   9360   8648 S  14.9   0.0    18,40 uresourced

$ getfattr -d -m - /sys/fs/cgroup/user.slice/user-1000.slice/[email protected]/app.slice/t3code.service
user.oomd_avoid="1"

$ busctl --user monitor (3s, counted)
   5665 Member=SetUnitProperties   # all from :1.21220 = /usr/libexec/uresourced --user

  Sender=:1.21220  Destination=:1.1  Path=/org/freedesktop/systemd1  Interface=org.freedesktop.systemd1.Manager  Member=SetUnitProperties
  MESSAGE "sba(sv)" {
          STRING "t3code.service";
          BOOLEAN true;
          ARRAY "(sv)" {
                  STRUCT "sv" { STRING "CPUWeight"; VARIANT "t" { UINT64 100; }; };
                  STRUCT "sv" { STRING "IOWeight";  VARIANT "t" { UINT64 100; }; };
          };
  };

# inotify IN_ATTRIB on app.slice for 2s
{'t3code.service': 5088}

Workaround

Either of:

  • Override the setting with a drop-in, then systemctl --user daemon-reload:
    # ~/.config/systemd/user/t3code.service.d/no-oomd-avoid.conf
    [Service]
    ManagedOOMPreference=none
  • Or disable uresourced for the user: systemctl --user mask --now uresourced.

If the user manager is already wedged, systemctl --user daemon-reexec breaks the loop without stopping running services (from uresourced#9).

Activity

  1. juliusmarminge commented on Oct 17, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Confirmed. apps/server/src/cloud/bootService.ts on main still emits ManagedOOMPreference=avoid (lines 109–112), with the comment that systemd-oomd ignores it when the watched cgroup is root-owned which is the usual distro setup (user-1000.slice). #17662 said the same: the preference does nothing there, and scopes are what protect the server.

    The CPU loop is a uresourced bug (benzea/uresourced#9), fixed in b9bf446 and shipped in uresourced v0.5.5. Fedora 44/45 still package 0.5.4, so stock installs keep hitting it. Until those catch up, a unit that sets ManagedOOMPreference=avoid can hang systemd --user.

    Since the setting is a no-op on typical distros, keeping this open as a bug on our side.

    Workaround (until a build without that line):

    # ~/.config/systemd/user/t3code.service.d/no-oomd-avoid.conf
    [Service]
    ManagedOOMPreference=none

    Then systemctl --user daemon-reload. If the user manager is already wedged, systemctl --user daemon-reexec breaks the loop.

  2. added
    acceptedfeature request accepted
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    needs more infoInitial triage showed no bug. Awaiting more info
    and removed
    needs more infoInitial triage showed no bug. Awaiting more info
    on Oct 17, 2026
  3. AriGr-GIT commented on Nov 3, 2026

    @AriGr-GIT

    Here's data from a second machine running Fedora 44 KDE Plasma 6.8.2, so this isn't GNOME-specific: t3 v0.1.6, systemd 259.10-1.fc44, uresourced 0.5.4-5.fc44. The Fedora request to ship uresourced 0.5.5 is https://bugzilla.redhat.com/show_bug.cgi?id=2559321 (the rawhide rebase is bug 2259354). F44 and F45 are still on 0.5.4.

    What starts the loop (the "at some point" above): any cgroup realize of t3code.service while uresourced is running. That means a service start, a systemctl --user daemon-reload while the service is active, or a set-property on it. Loops stack, and it's the second one that stops jobs from running:

    manager CPU trivial oneshot start
    no loop idle 12–19 ms
    1 loop (start) 87% 16–24 ms
    2 loops (+ reload while running) 95% 1.7–6.8 s
    3 loops 96% up to 8.3 s

    On this machine the service started at 13:44:07, and at 13:44:21 a daemon-reload ran while it was active. After that, t3code.service's next stop job waited 29 minutes. t3 service protect, t3 service uninstall and an in-service t3 service restart all reload while the service is active, so each of them adds a loop. Stopping the service doesn't end it: systemd recreates the stopped unit's empty cgroup on the next SetUnitProperties call and sets the xattr again. Here it kept running at about 630 calls/s after the stop.

    For #25185, I verified this live with a copy of the unit (ExecStart replaced with sleep), with and without the 90-t3code-protect drop-in:

    • With ManagedOOMPreference=avoid: 850–1,000 SetUnitProperties calls/s, and the manager at 95–96% CPU.
    • Without it: 0 calls on start or reload, and CPUWeight=1000/IOWeight=1000 stay as set. The ManagedOOMPreference=none drop-in workaround gives the same result.
    • OOMScoreAdjust=-900 and the weights make no difference.

    The preference isn't a no-op on Fedora, though. systemd-oomd-defaults sets ManagedOOMMemoryPressure=kill (80%) on the user app.slice. oomctl dump here lists [email protected], app.slice and the app-t3code* slices as monitored for memory pressure, all owned by UID 1000. oomd honours user.oomd_avoid when the candidate and the monitored cgroup have the same owner (oomd_fetch_cgroup_oom_preference(), systemd.resource-control(5)). So on Fedora, avoid really does lower t3code.service's priority for pressure kills in app.slice. Dropping it is still the right call while distros ship uresourced 0.5.4. But on Fedora it changes behaviour, and the reason in the code comment (a root-owned user-1000.slice) doesn't apply there. If keeping the preference matters, here's an alternative I tested: put the unit, with avoid, in its own top-level user slice outside app.slice. That doesn't loop. It does take the service out of app.slice's oomd monitoring and the protect MemoryLow, and it changes what CPUWeight=1000 competes against.

    Weights: even with the fixed uresourced 0.5.5, the first IN_ATTRIB after each start makes uresourced write its own policy weights (100/100 by default). It writes them as runtime drop-ins in $XDG_RUNTIME_DIR/systemd/user.control/t3code.service.d/, which override 1000/1000 until logout. Without ManagedOOMPreference there's no such event, and the 1000s stay.

    To recover without needing a job: systemctl --user kill uresourced.service, then systemctl --user start uresourced.service.

    Investigated with Claude (claude-opus-5-5) in Claude Code, running in T3 Code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions