Restore an instance when inbound activity races standby - #313
Closed
hiroTamada wants to merge 1 commit into
Closed
Conversation
hiroTamada
marked this pull request as ready for review
July 27, 2026 17:41
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit cac391a. Configure here.
A standby guest is only restored when a new inbound connection arrives, so a connection that is already open when the guest is suspended does not stall briefly, it hangs until the client gives up. The standby attempt releases the controller lock for the pause and snapshot, which takes long enough for a request to land mid-transition. The failing path already hands that state back to the reconcile flow, but the successful path dropped it in clearStateLocked and left the guest suspended with a live connection pointed at it. Undo the standby instead, reported as a raced_restored standby attempt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
hiroTamada
force-pushed
the
hypeship/auto-standby-dont-strand-live-connections
branch
from
July 27, 2026 17:56
cac391a to
abc15bf
Compare
hiroTamada
marked this pull request as draft
July 27, 2026 17:57
hiroTamada
marked this pull request as ready for review
July 27, 2026 17:57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
A standby guest is only restored when a new inbound connection arrives — wake-on-traffic does not exist. So a connection that is already open when the guest is suspended does not stall briefly, it hangs until the client gives up: no response, no
close, noerror, and every later request on that connection is lost too. Opening a second connection to the same guest works immediately, which makes it look like the first connection was individually poisoned.executeStandbyreleases the controller lock for the pause and snapshot, which takes long enough for a request to land mid-transition. The failing path already hands that state back to the reconcile flow, but the successful path dropped it inclearStateLockedand left the guest suspended with a live connection pointed at it.Change
After a successful standby, if inbound activity turned up while the snapshot was in flight, restore the instance instead of discarding that state. Reported as a
raced_restoredstandby attempt, with a WARN log. A restore that fails withErrInstanceNotFounddrops controller state, matching how the standby path already handles a deleted instance.RestoreInstanceis new on theInstanceStoreinterface; the Linux provider mapsinstances.ErrNotFoundontoautostandby.ErrInstanceNotFoundthe same wayStandbyInstancedoes.Scope
Deliberately narrow. Two adjacent hardening changes were cut from this PR and parked on
hypeship/auto-standby-hardening-parked, to be reviewed separately if wanted:TCPState.Activea denylist. OnlyNONE/TIME_WAIT/CLOSEwould stop counting, so an unrecognised state keeps the VM awake rather than stranding a live flow.SYN_SENT2(value 9, namedTCPStateListen) is currently classified as finished, the same gap Count half-open inbound connections as auto-standby activity #312 closed forSYN_SENT. This is fleet-wide behaviour with cost implications, so it deserves its own review.Neither is needed for the race this PR fixes.
Open question
There is a case where a live connection is not counted as active inbound at all, so the idle countdown starts and runs to completion while the client is mid-request. That is upstream of this fix and not addressed here —
matchesInboundConnectionForEventrequiresOriginalDestinationIPto equal the instance IP, which would not hold if a proxy hop to the guest is NAT'd. Worth resolving before adding more code in this area.The structural fix remains wake-on-traffic: an inbound packet for a suspended guest triggering a restore would turn this entire family of bugs into a latency hiccup instead of a hang.
Testing
go test -race ./lib/autostandby/...passes, as do the auto-standby tests incmd/api/api. Three new tests:The first two fail against the current controller. The remaining integration tests in
cmd/api/apineed a real hypervisor and registry and fail the same way onmainin this environment — I did not run those.🤖 Generated with Claude Code