Skip to content

fix(copy): keep lifecycle usable after missing source#799

Open
stephenlclarke wants to merge 1 commit into
apple:mainfrom
stephenlclarke:fix-copyout-missing-source-lock
Open

fix(copy): keep lifecycle usable after missing source#799
stephenlclarke wants to merge 1 commit into
apple:mainfrom
stephenlclarke:fix-copyout-missing-source-lock

Conversation

@stephenlclarke

Copy link
Copy Markdown

Summary

Finish copy-out coordination streams when guest-side source validation fails, preserve the original guest error across the task-group race, and release the container state lock so later lifecycle operations remain usable.

Motivation

apple/container#1927 reports that container cp hangs indefinitely when the guest source path does not exist. The same container then cannot be used by exec, stop, delete, or system shutdown because LinuxContainer.copyOut still owns its state lock.

The producer task receives the guest error before emitting metadata or establishing a vsock connection. Its sibling task waits on those asynchronous streams and does not unblock merely because the task group is cancelled. The group therefore cannot unwind. Closing both streams fixes the deadlock, while a small synchronized error state ensures the consumer cannot replace the useful guest error with an internal no metadata or vsock connection not established error.

Changes

  • Finish the metadata continuation and vsock listener on every producer failure.
  • Keep outer cleanup idempotent for successful and failed transfers.
  • Preserve the original guest error if either consumer guard observes stream termination first.
  • Add a VM integration regression that bounds missing-source copy, rejects coordination fallback errors, and runs a successful exec against the same container afterward.

Validation

swift build --disable-automatic-resolution \
  --product containerization-integration \
  -Xswiftc -warnings-as-errors
swift test --enable-code-coverage \
  --disable-automatic-resolution \
  -Xswiftc -warnings-as-errors
make check
./bin/containerization-integration \
  --kernel ./bin/vmlinux-arm64 \
  --max-concurrency 4 \
  --filter 'container copy out missing source does not block lifecycle'
./bin/containerization-integration \
  --kernel ./bin/vmlinux-arm64 \
  --max-concurrency 4 \
  --filter 'container copy out'
  • All 569 Swift tests in 79 suites pass with coverage instrumentation and warnings treated as errors.
  • Swift formatting and Hawkeye license checks pass.
  • The exact missing-source VM regression passes three consecutive runs, returns the original notFound guest-path error, and completes a subsequent exec on the same container.
  • All 3 matching copy-out VM integration cases pass together.
  • The committed diff has no whitespace errors.

Compatibility

There is no public API or successful-transfer behavior change. Missing guest paths now fail promptly and leave the container usable. apple/container can surface the lower-runtime error without adding its own lock or stream cleanup.

Related

Release Note Highlight

  • Fixes apple/container#1927: copying a missing container path now fails promptly without blocking later exec, stop, or delete operations.

Finish copy-out metadata and vsock streams when guest-side validation fails so the task group releases the container state lock. Preserve the original guest error across the coordination race and verify a later exec succeeds on the same container.

Fixes: apple/container#1927

Release-Highlight: Fixes apple/container#1927: copying a missing container path now fails promptly without blocking later exec, stop, or delete operations.
@wooii

wooii commented Jul 12, 2026

Copy link
Copy Markdown

I believe this PR fixed apple/container#1927.

Built container from source with containerization pointed at this PR #799 's branch (commit 9c5b9ee) via swift package edit.

Env: macOS 26.5.2, Apple Silicon (M4), Swift 6.3.3 / 6.3-RELEASE toolchains.

Results:

  • container cp a nonexistent path → fails immediately with a clear error instead of hanging. ✅
    Error: failed to copy from container test (cause: "internalError: "failed to copy from container test (cause: "unknown: "notFound: "copy: path not found '/run/container/test/rootfs/...'""")"")
    
  • Copying an existing path (e.g. /etc/os-release) → still works, returns promptly. ✅
  • container exec on the same container right after the failed copy → works, no hang. ✅
  • container stop on the same container → hit an XPC "Connection interrupted" error, but this looks like a separate issue. Haven't fully isolated whether it's related to this fix. ⚠️
    Error: internalError: "failed to stop container" (cause: "internalError: "failed to stop container test (cause: "interrupted: "XPC connection error: Connection interrupted"")"")
    Ensure container system service has been started with container system start.
    

Core issue from #1927 (indefinite hang on container cp to a missing path, and the resulting exec/stop lock-up) is resolved. Thanks @stephenlclarke and @lakshitsoni26!

stephenlclarke added a commit to stephenlclarke/containerization that referenced this pull request Jul 12, 2026
Tighten the VM regression for apple/container#1927 so a failed copy-out from a missing guest path rejects internal coordination fallback errors before proving the container can exec afterward.

Upstream-PR: apple#799

Fixes: apple/container#1927

Release-Highlight: Fixes apple/container#1927: copying a missing container path now fails promptly without blocking later exec, stop, or delete operations.
stephenlclarke added a commit to stephenlclarke/container that referenced this pull request Jul 12, 2026
Use stephenlclarke/containerization@79b675d so runtime builds include the apple#1927 missing-source copy-out regression alignment from apple/containerization#799.

Upstream-PR: apple/containerization#799

Fixes: apple#1927

Release-Highlight: Fixes apple#1927: missing container copy sources fail promptly without blocking later lifecycle operations.
stephenlclarke added a commit to stephenlclarke/container-compose that referenced this pull request Jul 12, 2026
Supports Docker Compose cp - archive streams for stdin-to-service and service-to-stdout copies by staging tar streams through the compose layer and existing Apple path-copy APIs.

Pins stephenlclarke/containerization@79b675d so the runtime carries the apple/container#1927 copy lifecycle regression coverage from apple/containerization#799.

Upstream scan found no direct Docker Compose copy-stream PR to import; adjacent Apple work reviewed: apple/container#963, apple/containerization#652, apple/container#1832, apple/container#1905.

Release-Highlight: Support Docker Compose cp - archive streams for stdin-to-service and service-to-stdout copies; includes apple/container#1927 copy lifecycle fix via apple/containerization#799.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: container cp on nonexistent source path hangs indefinitely; exec/stop on same container then hang too

2 participants