feat(rig): parvagues-protect — keep scsynth un-killable across every restart
PLN got "memory shortage avoided — parvagues-sc terminated because the system is low on memory". Nothing in the system had decided to kill it: systemd-oomd is disabled and has NEVER run, earlyoom/nohang inactive, and the kernel OOM killer left no trace in `journalctl -k` or `-b -1`. The string "memory shortage" appears in no journal at all, so the notification came from an app — source still unidentified, and currently the only warning that exists. THE MECHANISM — a stale binding, this rig's most expensive recurring shape. perf.sh:545 protects the rig BY PID (chrt -f 90, oom_score_adj -1000). systemd's user manager ships DefaultOOMScoreAdjust=200, so EVERY restart of parvagues-sc — crash, watchdog, or manual — hands scsynth back at +200, the most attractive OOM victim on the machine, with no realtime priority either. perf.sh is correct exactly once. On 2026-08-15 SC restarted 6+ times (four SIGSEGVs, e65e3a87) and spent the rest of the session naked. The tell: live processes read -1000 while `systemctl show` still says 200 — that gap IS the bug. WHY A SYSTEM UNIT. Measured, because it is easy to assume wrongly: OOMScoreAdjust=-1000 -> 100 OOMScoreAdjust=0 -> 100 OOMScoreAdjust=-500 -> 100 OOMScoreAdjust=200 -> 200 A --user unit CANNOT go below 100 and it clamps SILENTLY — no error, no log. Writing -1000 into parvagues-sc.service would look right in the file, look right in `systemctl show`, and do nothing. Lowering past the manager's own value needs CAP_SYS_RESOURCE. PLN: "make it system if useful ... this device is parvagues-pilled" / "i can sudo any good shit". WHAT SHIPPED tools/parvagues-protect.sh 2s sweep; only ever lowers oom, only ever raises priority, so it is idempotent and composes with perf.sh instead of fighting it. Logs ONLY changes — at 2s, "still fine" would be 43k journal lines a day, i.e. no logging. --check is read-only and unprivileged. tools/parvagues-protect.service root, hardened (three capabilities, no more), Nice=10 + IOSchedulingClass=idle so the protector is never itself a cost. tools/install-protect.sh COPIES the script to /usr/local/bin root:root 0755 rather than running it from the repo — a root unit with ExecStart under /home/pln is a privesc hole, unlike the user-owned watchdog. tools/gig-up.sh new SOFT check "SC un-killable". SOFT is a judgement, not an oversight: an unprotected rig still makes sound, and this gate's own rule is that HARD means "there is no gig". It never starts or stops anything — that stays the watchdog's job, and two supervisors with opinions about one process is a fight nobody wins. TWO BUGS FOUND WHILE BUILDING IT - `pgrep -f ardour` reported Ardour RUNNING when it was closed: it matched `bash .../tidal-ardour-autoroute.sh`, which has "ardour" in its path. I had already repeated that false positive to PLN as "Ardour up but engine not started". Now matches comm exactly, and --check PRINTS absent targets rather than skipping them silently. - `tools/check-audio-graph.sh` was +x on disk but git recorded 100644, failing the gate's own "tools executable" check. Fixed with update-index --chmod=+x (feedback_chmod_is_not_a_fix: chmod fixes your tree, not the repo). VERIFIED, both directions, because a check that cannot fail is decoration: --check returns 0 on the live protected rig, and against a decoy process at oom_score_adj=200/SCHED_OTHER it prints UNPROTECTED and exits 1 — that decoy signature is exactly what a freshly restarted scsynth looks like. NOT YET PROVEN: recovery after a real restart, which needs the unit installed (root). install-protect.sh ends by printing that verification.
Showing
tools/check-audio-graph.sh
100644 → 100755
File mode changed from 100644 to 100755
tools/install-protect.sh
0 → 100644
tools/parvagues-protect.service
0 → 100644
tools/parvagues-protect.sh
0 → 100644
Please
register
or
sign in
to comment