fix(e2e): headless TkAgg crash + readiness false-positive on forwards

Run 10536 reached pytest but every connect was reset: the simulator died at
import with 'Tkinter is needed' — lib/gui.py calls matplotlib.use("TkAgg")
unconditionally (an explicit use() overrides MPLBACKEND=Agg), and the port
probe passed instantly because it was accepting the localhost forwarders, not
the nodes.

- run_e2e.sh: patch meshtasticator lib/gui.py TkAgg->Agg before boot;
  probe readiness on the upstream host (docker daemon) when forwards are
  active; docker pull meshtastic/meshtasticd up front so the pull is off the
  simulator's node-boot path.
- e2e tests: cancel leftover loop tasks (watchdog) at loop teardown.
This commit is contained in:
2026-09-07 21:33:49 -07:00
parent 58b18d6260
commit ba31d79368
3 changed files with 44 additions and 4 deletions
@@ -143,6 +143,16 @@ def loop():
try:
yield _loop
finally:
# Cancel leftover tasks (e.g. a watchdog started by a failed connect
# whose disconnect teardown never ran) before closing the loop.
async def _shutdown():
for task in asyncio.all_tasks(_loop):
task.cancel()
try:
asyncio.run_coroutine_threadsafe(_shutdown(), _loop).result(timeout=5)
except Exception:
pass
_loop.call_soon_threadsafe(_loop.stop)
thread.join(timeout=5)