Skip to content

Stop screensaver busy-loop when branding text is missing - #11146

Open
caueguerra wants to merge 1 commit into
omacom:quattrofrom
caueguerra:fix/issue-11090
Open

caueguerra wants to merge 1 commit into
omacom:quattrofrom
caueguerra:fix/issue-11090

Conversation

@caueguerra

Copy link
Copy Markdown

If ~/.config/omarchy/branding/screensaver.txt is missing, ttfx exits immediately and omarchy-screensaver relaunches it in a tight loop. The keyboard poll lives inside while pgrep, so Escape never dismisses it — only Ctrl+C works. To the user this looks like a crashed fullscreen terminal flooding Error reading input file.

  • Prefer the user branding file when it exists, otherwise $OMARCHY_PATH/logo.txt (the same file omarchy branding screensaver reset already copies).
  • If neither file exists, exit instead of starting the loop.
  • Track the ttfx child and exit when it fails, so a missing/unreadable file cannot spin the CPU. A clean effect completion still relaunches the next random effect.

Fixes #11090

Fall back to $OMARCHY_PATH/logo.txt when the user branding file is absent,
and exit instead of relaunching ttfx when it fails to start.
@ssandys

ssandys commented Sep 29, 2026

Copy link
Copy Markdown

Another reason to merge this: the same pgrep -t guard also causes a fork storm when an omarchy-screensaver outlives its terminal, not only when the branding file is missing.

An orphaned instance (terminal gone, reparented to systemd --user, stdin /dev/null) has no controlling tty, so $tty is not a tty and pgrep -t never matches. The inner loop never runs, so the read/focus exit checks never happen, and the outer while true starts a new background ttfx as fast as fork() allows. On 2026-09-19 this pushed my machine (Ryzen AI 9 HX 370, 24 threads) to load average 106: about 230 forks/sec, about 195 live ttfx, and 10 stacked omarchy-screensaver instances, because the launcher's dedup doesn't see orphans (#10260). No memory pressure, just fork and CPU load.

It still happens on current master (4.0.0.r6687.gb18ab49). Repro, stopped after one second:

setsid -f omarchy-screensaver </dev/null >/dev/null 2>&1
sleep 1; pgrep -xc ttfx    # I get 8 -> 19 -> 29 at 0.25s steps
pkill -f '/omarchy-screensaver$'; pkill -x ttfx
hyprctl keyword cursor:invisible false

This PR tracks $ttfx_pid instead of the tty, so the inner loop does run for an orphan, screensaver_in_focus fails, and it exits on the first check. That fixes it. Locally I've been using [[ -t 0 && $tty == /dev/* ]] || exit 1 right after tty= as a stopgap.

@omarchybot omarchybot added the verified Omarchy Triage has verified that this issue is ready for final review label Oct 2, 2026
@omarchybot

Copy link
Copy Markdown
Collaborator

Reviewed at dd1d7c7 against quattro and verified on a disposable Omarchy worker. Nothing found that needs changing.

Reproduced. With ~/.config/omarchy/branding/screensaver.txt moved away and the screensaver launched in foot, the quattro script relaunched ttfx at about 246 new processes a second. This head falls back to $OMARCHY_PATH/logo.txt, draws it normally at about 7 processes a second, and Escape dismisses it. The orphaned-instance case @ssandys described also reproduces on quattro, with the branding file present: 106, 139, then 167 live ttfx within a second. With this head, the orphan exits immediately and starts none. With no branding file and no logo.txt, it exits without starting ttfx and the window closes.

Tests. The new test/shell.d/screensaver-test.sh passes 4/4 on the head. Run against the quattro script with the fix reverted, it fails on the busy-loop timeout. ./test/cli is green.

Exiting on a non-zero ttfx. The new loop exits the screensaver whenever ttfx exits non-zero, so I ran every one of the 37 ttfx 0.3.2 effects in a pty with the screensaver's own flags. All 37 exited 0, so a normal effect cycle does not dismiss the screensaver.

Related. It closes #11090. #6813, #11178 and #11626 rewrite the same loop as part of larger changes and will conflict with this one. None of them is a focused fix for this bug.

Second opinion. None ran: the reviewer answered a ping, but the day's review budget was already spent. This review is Claude Opus 5.5's alone, and that is why this is labelled verified and not ready. It waits on a second-opinion review, then on the maintainer.

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

Labels

bug Something isn't working verified Omarchy Triage has verified that this issue is ready for final review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Screensaver busy-loops and cannot be dismissed when branding/screensaver.txt is missing

3 participants