fix(ticc): hard re-init on sustained wedge to recover a re-enumerated TICC (I-160351a) - #306
Open
bobvan wants to merge 1 commit into
Open
fix(ticc): hard re-init on sustained wedge to recover a re-enumerated TICC (I-160351a)#306bobvan wants to merge 1 commit into
bobvan wants to merge 1 commit into
Conversation
… TICC (I-160351a) The reader reopens through a cached _SharedTiccPort whose acquire() only opens when serial is None (warm-reopen path, HUPCL preserved to avoid Arduino reboots). After the TICC USB re-enumerates — e.g. a power-cycle to clear a firmware hang — the old /dev node is gone but the cached fd is still non-None, so every reopen reuses the dead fd and never re-resolves the device path. The reader wedges: opens "succeed", LEDs flash, zero events, forever (observed 2026-07-24 on PiFace; only an engine restart recovered it). Add reset_shared_port() to close+null the cached port so the next acquire() does a fresh open (re-resolving /dev/ticcN), and escalate to it from ticc_reader() after a sustained stale streak (REINIT_AFTER_REOPENS, ~30 s), spaced so it keeps retrying. The warm reopen is left intact for transient hiccups (regression-tested). Tests: tests/test_ticc_reinit.py (5 new). All 37 TICC-touching tests pass. Full suite 2538 pass; the 21 unrelated failures are the known pre-existing full-suite logging-capture pollution (cf. fdbe017) — they pass in isolation. Hardware validation (recover a real re-enumerated TICC) pending a lab window. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The TICC reader reopens through a cached
_SharedTiccPort, andacquire()only opens the serial whenserial is None(the warm-reopen path — HUPCL is preserved so reopens don't reboot the Arduino). After the TICC USB re-enumerates — e.g. a power-cycle to clear a firmware hang — the old/devnode is gone but the cached fd is still non-None, so every reopen reuses the dead fd and never re-resolves the device path. The reader wedges: opens "succeed", trigger LEDs flash, zero events, indefinitely.Observed 2026-07-24 on PiFace: ~2.6 h stale (Rb reference lost) → device USB-power-cycled on return → the running reader never re-latched; only an engine restart recovered it.
Fix
ticc.py:reset_shared_port(port, baud)closes + nulls the cached_SharedTiccPortso the nextacquire()does a fresh_open_serial()that re-resolves/dev/ticcN.peppar_fix_engine.py::ticc_reader(): after a sustained stale streak (REINIT_AFTER_REOPENS≈ 30 s) escalate toreset_shared_port(), spaced so it keeps retrying while the device is absent. The warm reopen is left intact for transient hiccups (no needless Arduino reboots).Tests
tests/test_ticc_reinit.py(5 new): reset closes+nulls; unknown / wrong-key no-op; acquire-after-reset re-opens (the load-bearing recovery); warm reopen without reset does NOT re-open (regression guarding the no-reboot path).fdbe017) — they pass in isolation, unrelated to this change.Remaining: hardware validation
Needs a lab window + a TICC to power-cycle under a running engine: unplug/replug the TICC, confirm within ~30–60 s the reader logs "forcing hard re-init" and
ticc.csvresumes without an engine restart (the exact scenario that wedged Friday), and that normal-op transient reopens do not escalate. Tracked onI-160351a-delta.🤖 Generated with Claude Code