-
fix(rig): make a duplicate Ardour spawn structurally impossible, and log the decision · 3c00a9cb
The parked blocker was wrong about its own cause, which turned out to be the more useful finding. RIG UP answered one press with "ardour: launched — launched Ardour" while Ardour was already up. The two instances collided over the session lock and BOTH exited, taking all twelve orbit links with them mid-evening. The obvious suspect was is_running()'s `exe` regex, so the GIG UP rewire was parked behind "fix the detection first". Measured cold, the detection is fine. With Ardour running, is_running() returns True: argv0 is `ardour-9.7.0` (the wrapper /usr/bin/ardour9 is a shell script that exec's /usr/lib/ardour9/ardour-9.7.0) and `[Aa]rdour[-\d.]*$` matches it. Two presses in a row now correctly answer "running -> focus". The false negative is not reproducible, and -- the actual defect -- nothing anywhere recorded the decision, so the cause cannot be recovered. The incident had to be reconstructed from a chat transcript. So stop repairing a probe that measures correctly, and remove the probe's veto over an irreversible action: - A spawn guard keyed on a pidfile in $XDG_RUNTIME_DIR, consulted only after is_running() says no. It blocks while the pid we spawned is alive, plus a 20s window covering fork->exec->/proc visibility -- the one interval in which is_running() is legitimately blind. A pidfile rather than a module global because the two faces are two processes: the web Bridge and the perf-tray both call launch(), and an in-memory note in one is invisible to the other. - The guard re-checks process IDENTITY, not just liveness, so a recycled pid cannot jam it shut forever. A guard that fails closed permanently is its own outage. - _log() writes every launch decision to stderr -> the journal. - Ardour additionally sweeps a SUPERSEDED .pending aside before launching. No flag suppresses the "recover from crash?" modal -- only the file's absence does -- and that modal is exactly what the hot path must not contain (#136). It moves (never deletes, into the session's own dead/) and only when the session was SAVED AFTER the pending was written, i.e. a later save already superseded it. A .pending newer than the save holds unsaved captures; that one deserves a human, so its dialog is left to appear. Verified live, in this order: 1. cold launch -> SPAWNED pid 2708769, session path passed, 1 ArdourGUI 2. immediate 2nd press -> "running -> focus", still 1 ArdourGUI 3. is_running monkeypatched to lie False (the incident's exact condition) -> "NOT spawning -- we started pid 2708769 14.9s ago", still 1 ArdourGUI 4. same, 52s later (past SPAWN_GRACE) -> still refuses, on pid liveness 5. dead pid + old timestamp -> guard stands down, launching is possible again Also: the session chooser is gone from every entry point. Stock ardour9.desktop runs `ardour9` with no argument, so every launch from the menu asked "Tidal Live or Tidal Multi?" -- a modal in the hot path, and a chance to open the ARCHIVE by mistake (that same mixup produced a confidently wrong fader report on 2026-07-28). A user-local override sends the default click straight into Tidal Live and keeps the chooser as a right-click action. Stale comment corrected: the real binary is 9.7.0, not the 9.2.0 recorded there.PLN (Algolia) authored3c00a9cb
×