Repository navigation
Conversation
A fork's metadata is saved before the fork is brought to its target state. If Hypeman was killed in between, the fork stayed behind as an ordinary standby or paused instance: nothing marked it as unfinished, and a restore that was cut short kept its VMM, its memory and its vGPU. The caller had been disconnected without an answer and could not know the instance existed. A fork is now marked pending until its request succeeds, and pending forks are deleted at startup before the vGPU reconciler runs.
The pending mark now names the API process that is making the fork, by PID, start time and boot ID. The startup pass deletes a marked fork only when that process no longer exists. Without this, a second API process started against the same data directory, by mistake or to check a binary, would have deleted the forks that the running one was still bringing up.
This branch has not been deployed
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 fork that was still being brought up when Hypeman was killed stayed behind as an ordinary instance, holding its VMM, its memory and its vGPU. A fork is now marked pending until its request succeeds, and at startup Hypeman deletes the marked forks whose API process is gone.
Why it happened
A fork is made in two steps: its metadata is saved, then it is brought to the state the caller asked for. If the process dies in between, the fork stays wherever it got to. Nothing on disk says it is unfinished, so after the restart it looks like any other standby or paused instance. The caller was disconnected without a response and has no ID to delete.
For a QEMU guest with a vGPU this is expensive: a restore that was cut short keeps its VMM, the guest memory it had pinned and its virtual function until someone deletes the instance by hand.
What changes
StoredMetadata.ForkPendingis set when a fork's metadata is first saved, for instance forks and snapshot forks, and cleared once the fork has reached its target state. It names the API process that is making the fork, by PID, start time and boot ID. If clearing it fails, the fork request fails and the fork is cleaned up like any other failed fork, so a fork whose caller got a success is never still marked.RecoverInterruptedForksruns once at startup, before the API listens and before the vGPU reconciler starts. It deletes a marked fork only when the process named in the mark no longer exists: its PID is gone, belongs to a process started at another time, or was recorded before a reboot. When it cannot tell, it leaves the fork alone and logs a warning.Forks that completed are not touched, and a graceful restart still lets in-flight forks finish.
The owner check is there because nothing stops a second API process from starting against the same data directory, and the binary has no flags: running it to look for a version starts it. Without the check, that process would delete the forks the running one was still bringing up.
Testing
TestForkIsPendingOnlyUntilItsRequestSucceedscovers the mark through an instance fork, a snapshot fork, a fork left half-made and a snapshot of that fork.TestRecoverInterruptedForksDeletesOnlyForksWhoseProcessIsGoneruns the startup pass over a fork whose process exited (deleted), one whose process is still running (kept) and a finished one (kept). Two more tests cover the owner check: an exited process, a reused PID, an earlier boot, and a live PID with nothing else recorded.No VMM, virtual function, TAP or guest directory was left in any case, and the next fork passed. Without the change the same kill at 1.0 s left two forks
Pausedand two inStandby, with two VMMs still holding two virtual functions (two runs).Not covered