_emit() wrote to stdout synchronously from QEMU callback context — the iothread fires _on_uart_tx per UART byte, each becoming ~45 bytes of JSON. When the parent's pipe reader stalled, the 64 KB pipe filled and the write blocked INSIDE the QEMU iothread, freezing the entire guest. Observed as an intermittent (~1 in 10) boot hang: serial output stops right after the ROM log / rtcinit line — exactly where the accumulated boot events cross the pipe capacity — and never recovers. Direct worker harness runs (fast reader) never reproduced it; the browser/WS path did. Route _emit() through a bounded queue drained by a dedicated writer thread (opportunistic batching, one write per drain). Under extreme backpressure events are dropped and counted on stderr — losing telemetry beats freezing the emulated CPU. The shutdown path posts a sentinel and joins the writer so crash/system events still flush before os._exit. Verified on staging: 10/10 UI run/stop cycles + 8/8 direct harness boots with identical serial latency (~0.95s to first app output). |
||
|---|---|---|
| .. | ||
| app | ||
| scripts | ||
| sdk | ||
| tests | ||
| .env.example | ||
| Dockerfile | ||
| debug_qemu.py | ||
| mcp_server.py | ||
| mcp_sse_server.py | ||
| requirements.txt | ||