Repository navigation
experimental: upstream open-PR cherry-picks under test (tracking) - #4
Open
tiago-mitralab wants to merge 9 commits into
Open
tiago-mitralab wants to merge 9 commits into
tiago-mitralab wants to merge 9 commits into
Conversation
tiago-mitralab
force-pushed
the
experimental
branch
from
July 21, 2026 13:12
4fc7329 to
bbfbbd6
Compare
tiago-mitralab
force-pushed
the
experimental
branch
from
July 25, 2026 23:06
bbfbbd6 to
08293b0
Compare
tiago-mitralab
force-pushed
the
experimental
branch
from
July 26, 2026 01:15
08293b0 to
a93a91d
Compare
tiago-mitralab
force-pushed
the
experimental
branch
from
July 26, 2026 14:28
a93a91d to
bc00733
Compare
tiago-mitralab
force-pushed
the
experimental
branch
from
August 14, 2026 23:25
bc00733 to
7c17dff
Compare
tiago-mitralab
force-pushed
the
experimental
branch
2 times, most recently
from
August 31, 2026 14:52
3e85565 to
81cb62a
Compare
tiago-mitralab
force-pushed
the
stable
branch
from
September 15, 2026 11:23
a2b43fd to
4f02883
Compare
tiago-mitralab
force-pushed
the
experimental
branch
from
September 15, 2026 11:23
81cb62a to
9aa6edd
Compare
The UFFD handle goroutine had a TODO comment stating that the sandbox should be killed when handle() fails. In fact, this is already implemented: u.exit.SetError() triggers the sandbox exit watcher in sandbox.go (line ~1093) which calls sbx.Stop(). - Remove the stale TODO comment - Add error logging when handle() fails for better observability - Add unit tests covering handle failure behavior (exit error propagation, readyCh closure, handler error state, initial state, socket creation) (cherry picked from commit 3e30b03)
(cherry picked from commit c87310c)
(cherry picked from commit 7b54ed7)
WaitForExit was defined but never called, leaving the API-layer evictor as the sole mechanism to kill expired sandboxes. If the API service restarts the evictor goroutine stops and VMs accumulate indefinitely on nodes. Two changes: 1. setupSandboxLifecycle (sandboxes.go): replace sbx.Wait with sbx.WaitForExit so the lifecycle goroutine races against the sandbox TTL. On timeout, Stop() is called explicitly before the normal Close/cleanup path runs. 2. WaitForExit (sandbox.go): replace the one-shot time.After with a time.NewTimer loop that re-checks endAt after each fire. This means a KeepAlive that calls SetEndAt mid-flight correctly resets the node-side deadline instead of being silently ignored. Fixes e2b-dev#3193 (cherry picked from commit 0a823f1)
5 cases covering the two code changes in the parent commit: - AlreadyExpired: endAt in the past returns error immediately - ExitBeforeTTL: clean FC exit before TTL returns nil - ExitWithError: FC exits with error, error is wrapped and returned - KeepAliveExtendsTTL: SetEndAt extension resets the timer loop; sandbox is NOT killed at the original deadline - ContextCancelled: ctx cancel returns nil without killing All pass with -race. (cherry picked from commit 4826a8e)
When creating a sandbox, merge the template metadata's Context.EnvVars (which contains Docker image ENV directives) into the sandbox config's Envd.Vars before sending them to envd via POST /init. User-provided env vars from the SDK create() call take precedence over template defaults. Per-command env vars from process.start() still override both. This fixes both the standard resume path and the filesystem-only cold boot (reboot) path, where DefaultUser and DefaultWorkdir were already restored from template metadata but EnvVars was not. Closes e2b-dev#2268 (cherry picked from commit 5bfd55e)
…2b-dev#3037, process.go conflict resolved)
… as killed The node-side TTL from the WaitForExit cherry-pick fired at the sandbox end time, the same moment the API evictor acts, and called Stop with no stop reason. Two consequences: a sandbox the API meant to pause (auto-pause) could be killed first, since the node does not know about auto-pause, and every expiry it enforced read as a crash (ERROR, crashed label, and the per-team crash counter upstream added in 44932b6). The lifecycle now waits nodeTTLGrace (2 minutes) past the end time, so with the API up the evictor decides between pause and kill and the node only acts when the API never did. WaitForExit returns ErrSandboxTTLExpired for an expiry, and the lifecycle records StopReasonKilled and logs at Info. When the timer and the Firecracker exit are ready together, the exit wins, so a crash never reads as a TTL. The uffd handler logged its ERROR before upstream 394ed94 classified a stop during accept or handshake as benign, so a clean stop still logged an error. The log now follows the classification.
tiago-mitralab
force-pushed
the
stable
branch
from
October 23, 2026 02:20
2b56a0a to
ec09941
Compare
tiago-mitralab
force-pushed
the
experimental
branch
from
October 23, 2026 02:20
afd964b to
1e37e55
Compare
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.
Tracking PR for the
experimentalbranch. Do not squash-merge as a block, promote one cherry-pick at a time.Where this sits
The fork runs three branches, and this PR only makes sense against the middle one:
mainis a plain mirror ofe2b-dev/infra. Nothing of ours lands here, and no host should ever run it: it has no ublk.stableismainplus our permanent patches (ublk rootfs provider,MAX_STARTING_INSTANCES_PER_NODE,MAX_SANDBOXES_PER_NODE, and the multi-node static discovery). It is the default of the bootstraps.experimentalisstableplus the cherry-picks below, validated on a host before anything is promoted.Syncing is a fast-forward on
main, then a rebase ofstableover it, then a rebase ofexperimentaloverstable. The recurring conflict is always the same,sandbox.NewFactory, because upstream keeps changing its signature and ublk adds a parameter to it.Cherry-picks
Upstream status checked on 2026-07-26.
Still open upstream, so still ours to carry:
ip netns execwithnsenterto halve mount namespace copies on sandbox startup e2b-dev/runtime#3037 nsenter instead of ip-netns-exec (sandbox startup from >400ms to ~40ms); theprocess.goconflict was resolved by handroute.Dst == nil) panics at boot here, because our default route shows up as a non-nil0.0.0.0/0, so the cherry-pick accepts both shapesClosed upstream without merging:
Merged upstream, already gone from here:
Notes
envdfollows whatever version upstream ships; the bumps that came with e2b-dev#3099 and e2b-dev#3145 were dropped in the cherry-picks.The branch is force-pushed and re-rebased on every advance of
main, so a host must pin a SHA and never this branch name.