From 3e523576c2e414b55ff045ed5e06224cf820b430 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Wed, 16 Sep 2026 09:57:09 +0000 Subject: [PATCH] Pit toggle: ride out the stale-helper window after launch instead of failing First click on bonita after tron upgrade: 'The pit resolver couldn't start', and the helper log showed the 3.3.0 helper listening with no pit: line at all. The request had reached the OLD 3.2.8 helper, which the launcher replaces in the background a moment after launch; it answered 404 {error:not-found} and the sidebar showed the generic message. The background now retries /pit/start every 2s for up to 5 attempts while the answer is a 404 or nobody is listening, then reports helper-stale; the sidebar names that case (try again, or quit and relaunch) and shows the error code on the generic fallback. The helper logs unknown routes so a stale-version hit leaves a trace next time. Helper version 3.3.1. Co-Authored-By: Claude Fable 5.1 --- .../extensions/ai-sidebar/background.js | 40 ++++++++++++++----- .../extensions/ai-sidebar/sidepanel.js | 4 +- apps/desktop/launcher/tron-tor-helper | 3 +- apps/desktop/launcher/tronbrowser | 2 +- docs/moshpit-pit-toggle.md | 6 ++- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/apps/desktop/extensions/ai-sidebar/background.js b/apps/desktop/extensions/ai-sidebar/background.js index d7e09a7..cced25d 100644 --- a/apps/desktop/extensions/ai-sidebar/background.js +++ b/apps/desktop/extensions/ai-sidebar/background.js @@ -338,6 +338,34 @@ async function disablePit() { await setPitBadge(false); } +// The launcher replaces an out-of-date helper in the background right after +// launch (kill, settle, exec). A click in that window reaches the OLD helper, +// which has no /pit/* routes and answers 404 {"error":"not-found"}, or reaches +// nobody at all. Both are transient, so try for a few seconds before giving up, +// and say "stale helper" rather than "couldn't start" when it never catches up. +const PIT_START_ATTEMPTS = 5; +const PIT_START_RETRY_MS = 2000; + +function pitHelperIsStale(res) { + return !res || res.error === 'not-found' || (!res.started && typeof res.port !== 'number'); +} + +async function startPitViaHelper() { + let last = null; + for (let i = 0; i < PIT_START_ATTEMPTS; i++) { + if (i) await new Promise((r) => setTimeout(r, PIT_START_RETRY_MS)); + try { + last = await helperJson('/pit/start', 'POST'); + } catch (_) { + last = { error: 'unreachable' }; + continue; + } + if (!pitHelperIsStale(last)) return last; // a pit-capable helper answered, ok or not + } + if (last && last.error === 'unreachable') return last; + return { started: false, error: 'helper-stale' }; +} + async function stopPitViaHelper() { try { const ctrl = new AbortController(); @@ -356,15 +384,9 @@ chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => { sendResponse({ enabled: false, error: 'tor-on' }); return; } - let started; - try { - started = await helperJson('/pit/start', 'POST'); - } catch (_) { - sendResponse({ enabled: false, error: 'unreachable' }); - return; - } - if (!started || !started.started) { - sendResponse({ enabled: false, error: (started && started.error) || 'pit-failed' }); + const started = await startPitViaHelper(); + if (!started.started) { + sendResponse({ enabled: false, error: started.error || 'pit-failed' }); return; } await enablePit(); diff --git a/apps/desktop/extensions/ai-sidebar/sidepanel.js b/apps/desktop/extensions/ai-sidebar/sidepanel.js index 4a775f8..87796b8 100644 --- a/apps/desktop/extensions/ai-sidebar/sidepanel.js +++ b/apps/desktop/extensions/ai-sidebar/sidepanel.js @@ -337,8 +337,10 @@ async function togglePit() { showNetStatus('warn', 'Couldn’t reach the TronBrowser helper. Restart TronBrowser and try again, or run tron upgrade.'); } else if (err === 'pit-port-busy') { showNetStatus('warn', `Port ${PIT_SOCKS_PORT} on this machine is taken by another program, so the pit resolver couldn’t start.`); + } else if (err === 'helper-stale') { + showNetStatus('warn', 'TronBrowser’s helper is still the older version, which has no pit resolver. It is normally replaced a few seconds after launch — try 🤘 Pit again; if it keeps failing, quit TronBrowser completely and relaunch it.'); } else { - showNetStatus('warn', 'The pit resolver couldn’t start. See ~/.tronbrowser/tor-helper.log for the reason.'); + showNetStatus('warn', `The pit resolver couldn’t start (${safeHost(err || 'pit-failed')}). See ~/.tronbrowser/tor-helper.log for the reason.`); } } } catch (e) { diff --git a/apps/desktop/launcher/tron-tor-helper b/apps/desktop/launcher/tron-tor-helper index 36501f6..eb39bca 100755 --- a/apps/desktop/launcher/tron-tor-helper +++ b/apps/desktop/launcher/tron-tor-helper @@ -49,7 +49,7 @@ BUNDLED_DIR = os.environ.get("TRON_TOR_BIN_DIR", "") PIDFILE = os.environ.get("TRON_TOR_PIDFILE", "") # Bumped whenever the helper protocol/behaviour changes; the launcher kills a # stale helper so the current version always runs. -HELPER_VERSION = "3.3.0" +HELPER_VERSION = "3.3.1" _lock = threading.Lock() _proc = None # the running tor subprocess (or None) _ready = False # True once tor reported Bootstrapped 100% @@ -559,6 +559,7 @@ class Handler(BaseHTTPRequestHandler): elif path == "/pit/status": self._send(200, pit_status()) else: + log("no such route: %s (helper v%s)" % (path, HELPER_VERSION)) self._send(404, {"error": "not-found"}) def do_GET(self): diff --git a/apps/desktop/launcher/tronbrowser b/apps/desktop/launcher/tronbrowser index cd83ee3..0916c4f 100755 --- a/apps/desktop/launcher/tronbrowser +++ b/apps/desktop/launcher/tronbrowser @@ -175,7 +175,7 @@ if [ "$TOR" != "1" ]; then # running helper isn't this version — otherwise leave a healthy current # helper alone (don't drop an active Tor session). All backgrounded so the # kill+settle never holds up the browser launch. - HELPER_VERSION=3.3.0 + HELPER_VERSION=3.3.1 ( _pf="$DATA/tor-helper.pid" _rv="$(curl -fsS --max-time 1 http://127.0.0.1:9061/status 2>/dev/null | sed -n 's/.*"version"[^"]*"\([^"]*\)".*/\1/p')" diff --git a/docs/moshpit-pit-toggle.md b/docs/moshpit-pit-toggle.md index ded06c0..72e3ff2 100644 --- a/docs/moshpit-pit-toggle.md +++ b/docs/moshpit-pit-toggle.md @@ -75,7 +75,11 @@ would leak every lookup outside Tor, so: - If the DoH resolver did not answer the probe (offline, slow), the pit stays **on** and says so; names resolve as soon as it is reachable. - Failures the sidebar explains: the helper is not running (`tron upgrade`, - restart), port 9081 is taken, Tor is on. + restart), port 9081 is taken, Tor is on, or the helper is still an older + version. That last one is a launch race: the launcher replaces an out-of-date + helper in the background a moment after the browser starts, and a click in + that window reaches the old helper's 404. The background retries `/pit/start` + for about ten seconds before reporting it. ## Files