moq-boy: exit non-zero on reconnect give-up instead of hanging#1589
Conversation
The emulator runs on a spawn_blocking thread that loops forever. When the reconnect loop gives up after the 5m backoff timeout, run() returns Err and main returns it, which drops the tokio runtime. Dropping the runtime blocks indefinitely joining the blocking thread, so the process hangs as a zombie instead of exiting. systemd's Restart=always never fires, silently killing the games after a relay outage longer than the reconnect window. Exit explicitly via std::process::exit (0 on clean shutdown, 1 on error) so a real exit code reaches the supervisor without waiting on the runtime drop. The ctrl_c branch already did this; extend it to every exit path. moq-cli has no blocking task, so returning Err already exits non-zero cleanly; no change needed there. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe PR changes rs/moq-boy/src/main.rs so the top-level tokio::select! result is captured into a variable. The Ctrl-C branch now returns Ok(()) instead of calling std::process::exit directly. After the select!, main matches the result: it logs and exits with code 1 on error, or exits with code 0 on success, preventing implicit runtime drop while background tasks run. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 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 `@rs/moq-boy/src/main.rs`:
- Around line 449-453: The select arm handling Ctrl-C currently swallows any
io::Error by mapping tokio::signal::ctrl_c() to Ok(()); update the
tokio::select! arms (the block that awaits run(&config), jemalloc, and
tokio::signal::ctrl_c()) to propagate the Err from tokio::signal::ctrl_c()
instead of treating it as a clean shutdown — replace the `_ =
tokio::signal::ctrl_c() => Ok(())` arm with one that returns the Result from
tokio::signal::ctrl_c() (and add context as needed) so failures registering the
ctrl-c handler bubble up alongside errors from run and jemalloc.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 72411194-69f1-4686-a06f-a2f658fe9e3d
📒 Files selected for processing (1)
rs/moq-boy/src/main.rs
tokio::signal::ctrl_c() returns io::Result<()>; the `_ =` select arm matched both Ok and Err, so a failure registering the SIGINT handler would exit the process 0 at startup. Bind the result and add context so the error bubbles up alongside run() and jemalloc errors and exits non-zero. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem
moq-boy gives up reconnecting to the relay after the mandatory 5m backoff timeout (added in #1443), but the process doesn't exit — it hangs as a zombie. This defeats systemd's
Restart=always, so a relay outage (or any future deploy/relay rebuild) longer than the reconnect window silently kills the games and they never come back.Root cause
The emulator runs on a
spawn_blockingthread that loops forever (rs/moq-boy/src/main.rs:274). When the reconnect loop gives up,run()returnsErr,mainreturns it, and the tokio runtime is dropped. Dropping the runtime blocks indefinitely joining that never-ending blocking thread, so the process hangs instead of exiting. Thectrl_cbranch already side-stepped this with an explicitstd::process::exit(0); the give-up path did not.Fix
Capture the
select!result and exit explicitly viastd::process::exit(0 on clean shutdown, 1 on error) instead of returning frommain.process::exitterminates immediately without dropping the runtime, so it can't hang on the blocking thread, and a real non-zero exit code reaches systemd. The give-up error is logged on the way out.The 5m timeout is kept as-is (a permanent relay outage still surfaces as a non-zero exit rather than silently spinning forever), so
Restart=alwaysnow correctly restarts the service.moq-cli
No change needed. moq-cli has no
spawn_blockingtask, so returningErrfrommainalready exits non-zero cleanly. It shares the same 5m give-up shape but never happened to hit the window.Test plan
cargo check -p moq-boycargo clippy -p moq-boy(via nix toolchain)(Written by Claude)