fix(box): keep VM alive after container exits for vsock services#4
Merged
ZhiXiao-Lin merged 3 commits intomainfrom Apr 27, 2026
Merged
Conversation
When the container process exits (e.g., alpine's busybox init exits immediately after handling the command), the guest init previously called process::exit(), killing the VM before the vsock exec/PTY servers had a chance to start. This caused "WARN Exec socket appeared but heartbeat failed" and "Couldn't execute '/sbin/init'" errors. Fixes two issues: 1. wait_for_children(): container exit no longer terminates the VM. Instead, the guest init loops until SIGTERM from the host, keeping vsock services (exec, PTY, attestation) available. 2. Fallback entrypoint: resolve_oci_entrypoint() now uses /bin/sh instead of /sbin/init, which is universally available in minimal distros (Alpine, Debian, Ubuntu) and doesn't exit immediately. Also adds #[cfg(unix)] to 3 exec_command tests in layout.rs and fixes a struct literal that referenced Unix-only fields on Windows. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Windows volume paths like C:\Users\Temp:/data:ro contain multiple
colons (drive letter, path separators), causing the naive split(':')
parser to misidentify the host/guest boundary.
Rewrites parse_volume_mount() to:
- Use the parts array to determine host/guest boundary reliably
- Detect :ro/:rw mode suffix by checking the LAST colon-separated
segment (not the second-to-last, which fails for deep Windows paths)
- Reconstruct Windows paths by re-joining parts[0..guest_idx] with ":"
- Reject invalid mode suffixes (:invalid) by checking if the last
segment looks like a path component
- Reject volumes with fewer than 2 colon-separated parts
Fixes test_parse_volume_mount_{read_only,explicit_rw,invalid_mode}
on Windows (Cargo test target-dir conflicts prevented earlier runs).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
alpine:latest/sbin/initto/bin/sh(universally available)Root Cause
When the container process exits (e.g., Alpine's busybox init exits immediately after running
echo "Hello"), the guest init calledprocess::exit(), killing the VM before the vsock exec/PTY servers had a chance to start. This caused the heartbeat health check to fail.Changes
wait_for_children()now keeps the VM alive after container exit, only exiting on SIGTERM from the host/bin/shinstead of/sbin/init#[cfg(unix)]to 3 tests that use Unix-only methodsTest plan
cargo test -p a3s-box-runtime --lib: 780 passeda3s-box run alpine:latest -- echo "Hello"on Linux — verify no heartbeat warning and command succeedsa3s-box run -it alpine:latest -- /bin/shon Linux — verify PTY works🤖 Generated with Claude Code