fix(orchestrator): suppress EIO/ENXIO on sandbox cleanup after VM crash#3276
fix(orchestrator): suppress EIO/ENXIO on sandbox cleanup after VM crash#3276AdaAibaby wants to merge 3 commits into
Conversation
When a VM crashes or is OOM-killed, NBDProvider.Close() calls sync() before disconnecting the NBD device. If the device is already in an error state the BLKFLSBUF ioctl or fsync returns EIO, causing every abnormal VM exit to log "failed to cleanup sandbox: error flushing cow device" at ERROR level even though no data loss has occurred. Detect syscall.EIO from sync() and log at Warn instead of propagating the error, so the cleanup path completes cleanly after a VM crash. Fixes: e2b-dev#3273
There was a problem hiding this comment.
Code Review
This pull request updates the Close method in nbd.go to handle syscall.EIO errors when flushing the copy-on-write (COW) device, treating them as warnings since they likely indicate a VM crash. The reviewer suggested extending this logic to also ignore syscall.ENXIO errors, which can occur if the NBD device is already disconnected or cleared during a crash.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 82a2ec22e1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
After a VM crashes, NBDProvider.Close() calls sync() which issues BLKFLSBUF ioctl + fsync on /dev/nbdX. Because the NBD device is in error state the kernel returns EIO (or ENXIO if the device is already disconnected). Both errors are expected: the VM is gone and there is nothing to flush. Instead of suppressing the error in NBDProvider.Close() (which would also hide genuine disk-error EIO during Sandbox.Shutdown's flush-before- snapshot path), handle it in setupSandboxLifecycle — the one call site that is guaranteed to run only after VM exit. Non-EIO/ENXIO errors still propagate as ERROR, preserving alerts for real failures. Fixes: e2b-dev#3273
2cbcbcd to
90a738c
Compare
Summary
Closes #3273
When a VM crashes or is OOM-killed,
NBDProvider.Close()callssync()which issuesBLKFLSBUF ioctl + fsyncon/dev/nbdX. Because the NBD device is already in error state after the VM dies, the kernel returns:EIO— device is in error state (broken NBD connection)ENXIO— device is already disconnected/clearedBoth are expected — there is nothing to flush because the VM is gone. This caused every abnormal VM exit to emit a spurious ERROR:
Why not suppress in
NBDProvider.Close()directly?The initial approach (commit
82a2ec2) caughtEIOinNBDProvider.Close()itself. This was flagged by code review (Codex) as too broad:Sandbox.Shutdown()also callss.Close()with the explicit comment"This should properly flush rootfs to the underlying device"— a genuineEIOthere (e.g. host disk full) must still propagate as an error or a corrupt template could be silently published.Actual fix
Handle
EIO/ENXIOinsetupSandboxLifecycle()insandboxes.go— the only call site that is guaranteed to run after VM exit. TheSandbox.Shutdown()path is unaffected and still treatsEIOas a hard error.packages/orchestrator/pkg/server/sandboxes.go:Before / After
Before (every abnormal VM exit):
After:
Real non-EIO/ENXIO failures still surface at ERROR.
Test plan
kill -9; confirm no ERROR log for"failed to cleanup sandbox"and a WARN appears insteadSandbox.Shutdown()(pause/snapshot): confirm a genuine disk error still propagates as ERROR