fix(overlay): stop gamescope detection matching its own command line#212
Conversation
The overlay reported Gaming Mode on every desktop session. Both a user's CachyOS desktop and mine logged this with no gamescope running at all: [loadout-overlay] DISPLAY=:0 GAMESCOPE_DISPLAY=:0 GAMESCOPE_WAYLAND_DISPLAY=gamescope-0 `pgrep -f` matches against full command lines. This whole script is the argv of the `sh -c` that systemd runs, and the branch body contains GS_WAYLAND="gamescope-0" -- so the pattern "gamescope[- ]" matched our own shell. pgrep excludes itself but not its parent, which made the condition unconditionally true. (systemd strips the # comments, so the trigger is the live assignment, not the prose around it.) Match the real comm with `pgrep -x` instead. gamescope's kernel comm is "gamescope-wl", which is why the original `pgrep -x gamescope` failed and prompted the switch to -f in the first place; check both names. `-x` matches comm -- "sh" here -- so it cannot self-match. Verified both directions on CachyOS, driving the real ExecStart: desktop, no gamescope -> GAMESCOPE_DISPLAY=unset (was :0) real gamescope running -> GAMESCOPE_DISPLAY=:0, gamescope-0 (still detected) scripts/dev-overlay.sh keeps `pgrep -f`: it lives in a script file, so the pattern is not in that process's argv and cannot self-match. Applied to both the canonical unit and the installer heredoc, which are kept byte-identical. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The pgrep branch is not a fallback on SteamOS -- it is the only thing
that resolves the display there. Steam's environment in Gaming Mode
carries GAMESCOPE_WAYLAND_DISPLAY and DISPLAY but *not*
GAMESCOPE_DISPLAY, so the sed for it returns empty and control always
reaches the pgrep test. That made Gaming Mode detection rest entirely on
gamescope's comm string: if it is ever renamed, the Deck silently
degrades to desktop mode with no error, and the ":0" it assumes is a
guess that happens to be right today.
Steam already knows the inner X display, so read it. The pgrep -x test
stays as a genuine last resort.
Verified on SteamOS Gaming Mode (gamescope-wl live, Radeon 8060S):
steam environ: GAMESCOPE_WAYLAND_DISPLAY=gamescope-0
DISPLAY=:0
(no GAMESCOPE_DISPLAY)
real ExecStart: DISPLAY=:0 GAMESCOPE_DISPLAY=:0
GAMESCOPE_WAYLAND_DISPLAY=gamescope-0 (unchanged)
pgrep branch forced false:
GS_DISPLAY=:0 GS_WAYLAND=gamescope-0 (still resolves)
so the display is now derived rather than guessed, with no change to the
result on a real device.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Verified on real SteamOS Gaming Mode — no regression, root cause confirmed, one hardening pushedTested on SteamOS in live Gaming Mode ( Root cause confirmed from the live argvThe So No regression in Gaming ModeDrove both logics against the real thing:
It also fixes a live bug on Deck desktop mode, where the self-match currently forces
|
✅ Verified end-to-end on a real Steam Deck — both modes, installed buildInstalled this branch's unit on SteamOS and drove both session modes. All four readings measured on hardware:
The bug reproduces exactly as described, and the fix corrects it with no change to Gaming Mode. Gaming Mode — no regressionInstalled build, fresh PID, byte-identical to the pre-fix baseline:
Desktop Mode — the fix, and the behavioural checkAnd the overlay hides and shows correctly in Desktop Mode — confirmed by the maintainer on the installed build. That last part was the only real risk in this PR and worth stating plainly: this flips Note on the
|
Problem
The overlay reports Gaming Mode on every desktop session. Both a user's CachyOS desktop and mine log this with no gamescope running at all:
Confirmed live on my machine —
pgrep -x gamescope-wlreturns nothing, yet the unit exportsGAMESCOPE_DISPLAY=:0and the app follows it:[display-detect] using $GAMESCOPE_DISPLAY=:0on a plain Plasma Wayland session.Root cause
pgrep -fmatches against full command lines. This entire script is theargvof thesh -cthat systemd runs, and the branch body containsGS_WAYLAND="gamescope-0"— which matches the patterngamescope[- ].pgrepexcludes itself but not its parent shell, so the condition is unconditionally true.Verified by running the exact ExecStart payload on a box with no gamescope process: it still printed
GAMESCOPE_DISPLAY=:0, andpgrepreported its own shell PIDs as the matches.(systemd strips the
#comments before exec, so the trigger is the livegamescope-0assignment, not the prose around it — confirmed against theExecStartproperty dump.)Fix
Match the real comm with
pgrep -x:gamescope's kernel comm is
gamescope-wl— which is exactly why the originalpgrep -x gamescopefailed and prompted the switch to-f. Verified against a real process:pgrep -x gamescope-wl→ match;pgrep -x gamescope→ no match. Both names are checked in case a build differs.-xmatches comm (shhere), so it cannot self-match.Verification
Both directions tested on CachyOS by driving the real ExecStart from this file (probe unit generated from the service via
sed, echoing instead of exec'ing the launcher):GAMESCOPE_DISPLAY=unset GAMESCOPE_WAYLAND_DISPLAY=unset✅ (was:0/gamescope-0)GAMESCOPE_DISPLAY=:0 GAMESCOPE_WAYLAND_DISPLAY=gamescope-0✅ still detectedSo the false positive is gone with no regression to genuine gamescope detection.
Scope
scripts/dev-overlay.sh:49keepspgrep -fdeliberately — it lives in a script file, so the pattern is not in that process'sargvand cannot self-match. Left alone rather than churned.Applied to both
loadout-overlay.serviceand thescripts/install.shheredoc, kept byte-identical (perc0f36c4, these drift).Why this matters beyond the log line
Gaming Mode isn't cosmetic — it gates Steam SIGSTOP-on-open, gamescope-resolution window sizing, and CEF plugin injection. A desktop session falsely in Gaming Mode takes all those paths.
Notes
Separate from #211 (the mesa/zink crash fix) so each can be reverted independently. Both touch the same ExecStart region, so whichever lands second needs a rebase. #211 is the one that actually gets the overlay open again; this one is a correctness fix found alongside it.
🤖 Generated with Claude Code