From 62c34fe80cd8e05b6cb092f53b41869cb1656f2c Mon Sep 17 00:00:00 2001 From: Waters Church Date: Sun, 27 Sep 2026 10:55:44 -0400 Subject: [PATCH] Timers 1.5.1: a failed capture-tool build must not park the listener forever MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found live on AB: the build failed (its CLT is broken), the compiled binary was then copied in by hand — and the listener never noticed. It had seen 'build in flight' and stopped scheduling retries, waiting for ensureCaptureBinary's onReady, which only fires on SUCCESS. The tile said 'Capture tool building…' indefinitely with a working binary on disk; only a module remount recovered it. onReady stays as the fast path; the 30 s retry now stays armed in every not-ready state, so a failed build keeps re-checking and a binary that arrives from outside (scp'd to a machine that can't compile) is picked up within half a minute. Reproduced the exact shape in a swiftc-less environment: build fails, binary copied in at 3 s, retry at 30 s spawns it (the capture's own unknown-device answer proves the real binary ran) — previously a permanent deadlock. Co-Authored-By: Claude Fable 5 --- modules/propresenter-timers/ltc-listener.js | 10 +++++++--- modules/propresenter-timers/module.json | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/propresenter-timers/ltc-listener.js b/modules/propresenter-timers/ltc-listener.js index cc43b93..d98a1b8 100644 --- a/modules/propresenter-timers/ltc-listener.js +++ b/modules/propresenter-timers/ltc-listener.js @@ -191,9 +191,13 @@ function createLtcListener({ device, channel, moduleDir, log, onUpdate }) { }); if (!tool.ready) { report({ error: tool.error, detail: tool.detail }); - // A build in flight restarts us itself when it lands; anything else is - // config-shaped and should back off hard rather than spin. - if (tool.error !== TOOL_BUILDING) scheduleRestart(BAD_CONFIG_RETRY_MS); + // onReady is only the FAST path (a successful build restarts us at + // once). The slow retry must stay armed regardless: a failed build + // never calls back, and a binary can also arrive from outside — scp'd + // in on a machine whose toolchain can't build (AB's broken CLT). + // Waiting on onReady alone deadlocked exactly that way in production: + // "Capture tool building…" forever, with a working binary on disk. + scheduleRestart(BAD_CONFIG_RETRY_MS); return; } diff --git a/modules/propresenter-timers/module.json b/modules/propresenter-timers/module.json index a825788..7e17779 100644 --- a/modules/propresenter-timers/module.json +++ b/modules/propresenter-timers/module.json @@ -1,7 +1,7 @@ { "id": "propresenter-timers", "name": "Timers", - "version": "1.5.0", + "version": "1.5.1", "proddash": ">=1.4.0", "description": "Timers, Clocks, and LTC From configured Modules", "provides": [ -- 2.54.0