feat(runtime): add the host-process WorkloadRuntime backend (RIG-3512) - #1120
Merged
Merged
Conversation
|
😎 This pull request was merged. |
|
Compass engineering docs preview: https://compass-service-owner-rig-35.compass-eng-docs.pages.dev Deployed from |
rigel-mintaka
added this pull request to stack #1126
September 12, 2026 00:25
This was referenced Sep 12, 2026
Merged
mattwilkinsonn
approved these changes
Sep 12, 2026
Implements the frozen nine-method WorkloadRuntime as direct host child processes and registers it in SelectBackend as `host`. The default stays podman: host is opted into explicitly, never fallen back to. Create/Start/Exists are bookkeeping over a per-agent 0700 state dir; MountLabel and Resize are degenerate by construction and say so at the method, Resize returning a typed unsupported error rather than a silent success. Exec and ExecStreaming accept only the Runner's own euid as AsUser, erroring on any other uid rather than running it wrong. A leaked grandchild holding the output pipe past its parent's exit makes Go's WaitDelay fire on a command that already completed. That is not a spawn failure: the exit status is real, so it is reported with the captured output instead of being discarded. The child inherits the Runner's environment with ExecSpec.Env overriding per key. A host child has no image to supply a baseline, so without it even PATH is unset and an unqualified command cannot resolve. Joins the shared WorkloadRuntime contract suite as an untagged leg. The podman and microVM legs are gated on an engine or KVM being present, so the shared contract ran against nothing in most jobs; the host backend needs neither. The rows the engine legs pinned to a baked uid 1000 now take the uid from caps, because the host backend runs as the Runner's own euid and that is 1001 on a stock hosted runner. The defaults keep every podman and microVM assertion byte-identical. Co-authored-by: Matt Wilkinson <matt@rigel.build>
…pEff assertion (RIG-3512) Remove read handle.proc after dropping the mutex while ExecStreaming writes it under the mutex. Besides the data race, Remove could see a nil proc for a child being spawned, skip the kill, and drop the handle -- leaving a live process under the operator's uid that nothing owns. The capture now happens in the same critical section as the map delete. The shared CapAdd row asserted an all-zero CapEff. A host child inherits the Runner's capabilities, so that asserted the test runner is unprivileged rather than that CapAdd was ignored, and would red on a CI runner with any capability. The host leg now compares the child's set to the Runner's own; the engine legs keep the all-zero assertion. Also drops the write-only handle env field rather than document it as honored, and stops the egress and state-root comments implying protections the tier does not have. Co-authored-by: Matt Wilkinson <matt@rigel.build>
… mid-spawn (RIG-3512) ExecStreaming records the process on the handle only after cmd.Start, so a Remove landing in that gap found no process to kill, deleted the handle, and wiped the state dir under a child that was already running. Nothing could reach that child afterwards, because Remove addresses a workload by id and the id was gone. ExecStreaming now re-checks the handle is still present before recording the process, and reaps its own child and errors when it is not. The concurrency test's comment claimed it covered this; it does not, so it now says it guards the data race only. A test for the window itself is not included: the interleaving is not reachable from the public API, because the handle lookup rejects a removed id before the spawn begins. Co-authored-by: Matt Wilkinson <matt@rigel.build>
The previous commit shipped this fix untested on the grounds that the window was unreachable from the public API. That was wrong: startedHandle releases the lock before returning, so the whole span from there through the spawn is lock-free and a concurrent Remove can land anywhere inside it. An after-spawn hook, nil in production, lets the test occupy that gap directly instead of racing for it. Reverting the re-check now fails the test in milliseconds; the race-based attempt could not fail at all, because the handle lookup rejects a removed id before the spawn starts and won almost every interleaving. Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka
force-pushed
the
compass-service-owner/rig-3512-host-backend
branch
from
September 12, 2026 19:37
7701fa8 to
fdb1562
Compare
mattwilkinsonn
approved these changes
Sep 12, 2026
trunk-io
Bot
deleted the
compass-service-owner/rig-3512-host-backend
branch
September 13, 2026 00:29
|
This pull request was merged into |
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.
This PR is part of a stack containing 10 PRs:
mainImplements the frozen nine-method WorkloadRuntime as direct host child
processes and registers it in SelectBackend as
host. The default stayspodman: host is opted into explicitly, never fallen back to.
Create/Start/Exists are bookkeeping over a per-agent 0700 state dir;
MountLabel and Resize are degenerate by construction and say so at the
method, Resize returning a typed unsupported error rather than a silent
success. Exec and ExecStreaming accept only the Runner's own euid as
AsUser, erroring on any other uid rather than running it wrong.
A leaked grandchild holding the output pipe past its parent's exit makes
Go's WaitDelay fire on a command that already completed. That is not a
spawn failure: the exit status is real, so it is reported with the
captured output instead of being discarded.
The child inherits the Runner's environment with ExecSpec.Env overriding
per key. A host child has no image to supply a baseline, so without it
even PATH is unset and an unqualified command cannot resolve.
Joins the shared WorkloadRuntime contract suite as an untagged leg. The
podman and microVM legs are gated on an engine or KVM being present, so
the shared contract ran against nothing in most jobs; the host backend
needs neither. The rows the engine legs pinned to a baked uid 1000 now
take the uid from caps, because the host backend runs as the Runner's own
euid and that is 1001 on a stock hosted runner. The defaults keep every
podman and microVM assertion byte-identical.
Co-authored-by: Matt Wilkinson matt@rigel.build