fix(scripts): sold-client-ports guard self-matched its own shell, wedging it ON

`pgrep -f FIFA17.exe` matched the remote shell executing it -- the SSH command line
contains the literal pattern -- so fifa_running() always returned True and the port
switcher could never edit openfut.cfg. It refused with "REFUSING to edit ... while a
FIFA client is running" moments after FIFA had actually exited.

Fail-closed, so nothing unsafe happened, but the guard was permanently stuck and
blocked the A/B entirely.

Now matches /proc/<pid>/comm exactly, which is the executable name: the invoking
shell reads as zsh and cannot self-match, while a genuine FIFA process still does.
Validated both directions with the same loop -- it found pid 36958 while FIFA was up,
and reports gone once it exited. Still fail-closed on read errors.

The lesson generalises: a pattern-matching process guard checked over a transport
that carries the pattern in its own argv is self-satisfying, and a guard that can
only ever say "yes" is not a guard.
This commit is contained in:
funman300
2026-08-18 02:33:53 +00:00
parent 9ffbd651b1
commit fbe29da05b
+15 -1
View File
@@ -54,7 +54,21 @@ def parse(text):
def fifa_running():
return bool(ssh("pgrep -f FIFA17.exe || true").strip())
"""True if a real FIFA 17 process exists on the client.
Matches /proc/<pid>/comm exactly rather than `pgrep -f FIFA17.exe`: the pattern
form self-matched the remote shell running it (the SSH command line contains the
literal string), so the guard was permanently stuck ON and could never report
"not running". comm is the executable name, so the shell reads as zsh/bash and
only a genuine FIFA process matches. Still fail-closed: any read error or
unexpected output is treated as "running".
"""
out = ssh(
"for d in /proc/[0-9]*; do "
"[ -r \"$d/comm\" ] && [ \"$(cat $d/comm 2>/dev/null)\" = FIFA17.exe ] "
"&& echo ${d#/proc/}; done || true"
).strip()
return bool(out)
def show():