Fix: prevent duplicate AutoRelog retries (#3186) - #3188
Conversation
|
🔍 Automated Code ReviewSummaryThe independent diff review found two medium-severity race conditions and one low-severity coverage gap. Both races were fixed in Findings✅ Strengths
✅ Resolved findings
|
Login rejections could schedule and execute multiple restarts for one failure while leaving no usable console route during reconnect delays. Changes: - Bind failure and restart work to immutable connection attempts - Coalesce automatic retries while allowing explicit settings replacement until commit - Preserve held bots and offline command routing across failed logins - Add deterministic retry, ownership, and routing regression tests Fixes #3186
Prepare offline routing before restart requests become observable, reject stale route owners, and wait for source-client cleanup before executing automatic retries. Add deterministic publication-order, cleanup-gate, and stale-route regression tests.
e74bcaf to
5655e3f
Compare
Summary
Fixes the duplicate AutoRelog decisions and unreliable reconnect ownership reported in #3186.
/recoand/connectto replace the pending settings snapshot until commit.Root cause
A login rejection was reported twice.
Protocol18.Login()first delivered the realLoginRejectedreason and server message, then returnedfalse; theMcClientconstructor independently synthesized a secondConnectionLostdecision. The restart coordinator could accept that duplicate after the first request entered its callback, causing two retry reservations and two reconnect waits for one rejection.The reconnect path also removed the client input route without installing an offline route. Commands entered during a delay were silently discarded. In addition, bots held across restart were restored only after a successful login, so they were absent on alternating failed attempts.
Fix
Login()so original rejection reasons and messages reach them on every attempt.Automated validation
source tools/mcc-env.sh && mcc-build: passed with 0 errors. Existing NuGet vulnerability warnings remain.MinecraftClient.Testssuite: passed, 31/31 tests after the independent-review fixes.git diff --check: passed.while (!packetQueue.IsCompleted).The docs build reached the repository's existing missing-translation-file problem before rendering. No translation files or user-visible C# strings were changed.
Real-server proof
All Minecraft clients used random offline-mode bot names and isolated temporary configs under
/tmp/mcc-debug. No personal account or repository-root config was used./helpproduced command output and/quitexited./help,/reco, and/connectwere accepted during the delay. A replacement/connect localhost:25566committed and failed at that port; replacing it withlocalhost:25565let the same process join after whitelist removal./quithandled through that route.m3186r35cbdfcompleted 203 real whitelist rejections, 203 waits, and 203 restarts. After whitelist removal, that same process joined successfully and handledquitcleanly.Ignore_Kick_Message=false, the exact whitelist rejection text, and a fixed 3-second delay against one server. Every bot completed exactly 10 rejections, 10 matching waits, and 10 restarts with zero fatal errors. After whitelist removal, all seven processes joined without being restarted, and all seven handledquitcleanly.The server logs independently recorded
m3186e6d086c joined the gameon 1.20.4 at 15:56:02 andm3186e6d086f joined the gameon 1.21.11 at 16:00:32. Both were the same MCC processes that had been cycling through whitelist rejections.Preserved proof logs:
/tmp/mcc-debug/issue3186-fixed-1204-ignore/mcc-debug.log/tmp/mcc-debug/issue3186-fixed-12111-ignore/mcc-debug.log/tmp/mcc-debug/issue3186-fixed-12111-match/mcc-debug.log/tmp/mcc-debug/issue3186-review-races/mcc-debug.log/tmp/mcc-debug/issue3186-review-seven//tmp/mcc-debug/issue3186-fixed-stress/The shared 1.21.11 server was left running and its whitelist was restored to off. Server-side
handleDisconnection() called twicewarnings are vanilla cleanup messages and did not correspond to duplicate MCC retry decisions.The ten-process run was a local generic transport-failure continuity soak because the sandbox denied its child processes permission to open sockets. It can prove that all workers keep cycling with one retry decision per failed attempt, but not server admission. Ten-client server admission and the fault-proxy recovery matrix remain unexecuted because the environment stopped granting unsandboxed process launches. The single-client server recovery matrix passed on both requested protocol generations, so this PR does not claim to identify or bound every possible synchronous network stall.
Process notes
Fixes #3186