fix(zaparoo): shut down frontend before FPGA reconfig to stop atari launch freeze#13
Conversation
…freeze Launching a core from the launcher frontend could hard-freeze the device (silent black screen, reboot required) — reliably reproduced on atari5200 /atari800. The frontend process stays alive holding mmaps into /dev/fb0, the HPS framebuffer the FPGA scans out over the f2sdram bridge. fpga_load_rbf calls do_bridge(0) to reset that bridge while the frontend is still mapped to it, deadlocking the AXI bus mid-reconfiguration. Upstream has no frontend, so it never hits this. Move the frontend teardown ahead of reconfiguration: call alt_launcher_shutdown() at the top of fpga_load_rbf so the frontend (and its framebuffer) is gone before do_bridge(0)/socfpga_load. The call is idempotent, so app_restart's existing call is left untouched. Also harden the frontend VT takeover: replace the unbounded video_chvt() (VT_WAITACTIVE blocks forever if the frontend stalls bringing up video) with a bounded VT_ACTIVATE + VT_GETSTATE poll, and defer the takeover until the FPGA is ready. This fixes a separate poll-cothread wedge during menu+frontend bring-up after a 15kHz core.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughLauncher VT switching now waits for FPGA readiness and uses a bounded activation loop. FPGA loading now shuts down the launcher before OSD disable and bridge reset. ChangesLauncher and FPGA reconfiguration timing
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@support/zaparoo/alt_launcher.cpp`:
- Around line 485-490: The activation wait loop in switch_to_launcher_vt is
blocking the poll cothread by using usleep inside a fixed retry loop. Replace
the busy-sleep with a cooperative yield to the libco scheduler (for example via
scheduler_yield() in the alt_launcher_poll/finalize_spawn path) and keep the
bounded retry behavior using a wall-clock deadline or equivalent non-blocking
timeout logic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f03b4a06-1ec3-4cc1-a9c4-3dee46076d64
📒 Files selected for processing (2)
fpga_io.cppsupport/zaparoo/alt_launcher.cpp
switch_to_launcher_vt() ran in the poll cothread. usleep() in libco's cooperative single-thread model sleeps the whole process, so the bounded VT wait stalled both cothreads (no UI/OSD, no poll) for up to 500ms. Replace the fixed usleep retry loop with a wall-clock deadline (GetTimer/CheckTimer) plus scheduler_yield(), keeping the same bound while staying cooperative.
Problem
Launching a core from the launcher frontend could hard-freeze the device — silent black screen, serial output dead, reboot required. Reliably reproduced on atari5200/atari800; the identical launch works on stock MiSTer.
Root cause (traced)
The freeze is silent, right after
Bitstream size: N bytes, with no further serial output:Every loop in the path after that print (
fpgamgr_program_write,fpgamgr_program_poll_*) is bounded and prints on error — there is no software infinite loop and no silent failure path. A totally silent, reboot-requiring freeze is therefore a hardware AXI bus deadlock during FPGA reconfiguration.The only fork-unique factor: the frontend process is still alive, holding mmaps into
/dev/fb0— the HPS framebuffer the FPGA scans out over the same f2sdram bridge thatfpga_load_rbfresets viado_bridge(0). The fork only killed the frontend afterward, inapp_restart. So the live frontend + active framebuffer overlap the bridge teardown → bus deadlock. Upstream has no frontend, so it never hits this. The atari bitstream just reproduces the timing window reliably.Fix
fpga_io.cpp: callalt_launcher_shutdown()at the top offpga_load_rbf, so the frontend (and its framebuffer) is torn down beforedo_bridge(0)/socfpga_load. The call is idempotent, soapp_restart's existing call is left untouched.support/zaparoo/alt_launcher.cpp: harden the VT takeover — replace the unboundedvideo_chvt()(itsVT_WAITACTIVEblocks forever if the frontend stalls bringing up video) with a boundedVT_ACTIVATE+VT_GETSTATEpoll, and defer the takeover until the FPGA is ready. Fixes a separate poll-cothread wedge during menu+frontend bring-up after a 15kHz core.Both changes are surgical and fork-friendly (one added line in the upstream file plus fork-owned code) — minimal merge surface, no upstream reformatting, no Makefile change.
Testing
Built via
./docker-build.shand deployed to hardware:Summary by CodeRabbit