Skip to content

Fix build context symlink resolution and XPC concurrency#1922

Closed
lakshitsoni26 wants to merge 1 commit into
apple:mainfrom
lakshitsoni26:fix-symlink-resolution
Closed

Fix build context symlink resolution and XPC concurrency#1922
lakshitsoni26 wants to merge 1 commit into
apple:mainfrom
lakshitsoni26:fix-symlink-resolution

Conversation

@lakshitsoni26

@lakshitsoni26 lakshitsoni26 commented Jul 8, 2026

Copy link
Copy Markdown

Fixes #1899

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Motivation and Context

This PR resolves two critical regressions in the build system:

  1. ADD/COPY Symlink Context Resolution: Fixes an issue where tar buildkit generation was failing to properly include and resolve symlinked files in the build context. In URL+Extensions.swift, the path hierarchy functions (relativeChildPath and parentOf) were overly aggressively resolving symlinks via .standardizedFileURL. This is fixed by implementing a safe stripPrivatePrefix function. In BuildFSSync.swift, FileInfo.init was incorrectly attempting to resolve paths instead of reading the raw target from disk, which has now been fixed using destinationOfSymbolicLink(atPath:).
  2. XPC Concurrency Hangs: Fixes a concurrency deadlock/hang issue within XPCClient when iterating over asynchronous stream states under high loads.

Testing

  • Tested locally
  • Added/updated tests
  • Added/updated docs

Local Test Output:
Ran make cli && swift test --filter TestCLIBuilderSerial end-to-end:
✔ Suite TestCLIBuilderSerial passed after 213.792 seconds.
✔ Test run with 44 tests in 1 suite passed after 213.792 seconds.

Screenshot 2026-07-09 at 12 19 39 PM

@lakshitsoni26

Copy link
Copy Markdown
Author

🐛 Root Cause Analysis: ADD/COPY Symlink Context Resolution

For context, this PR fixes a deep path-resolution bug that was causing the buildkit tarball generation to silently strip symlinks from the build context, resulting in No such file or directory errors during Dockerfile execution.

The Bug:
During build context generation, BuildFSSync.swift relies on methods in URL+Extensions.swift (specifically relativeChildPath and parentOf) to map file hierarchy. Previously, these methods unconditionally evaluated paths using .standardizedFileURL.

Because .standardizedFileURL triggers the system's realpath equivalent, it immediately resolves symlinks on the disk.

  1. When a symlink like Test3Source2/Dest (pointing to ../Test3Source/Source) was passed in, .standardizedFileURL resolved it instantly.
  2. The symlink's actual name (Dest) was discarded in memory, and the path was mapped as its destination (Test3Source/Source).
  3. Consequently, the tarball generated for buildkit completely omitted the symlink, replacing it with a duplicate of its target directory.
  4. When RUN cat Test3Source2/Dest/test.txt executed in the container, it failed because Dest was never sent to the daemon.

The Fix:
The original usage of .standardizedFileURL was a heavy-handed workaround to handle macOS temporary directory mismatches (i.e., /var/ vs /private/var/).

To safely fix the mismatch without aggressively resolving workspace symlinks:

  1. Replaced .standardizedFileURL in URL+Extensions.swift with a targeted stripPrivatePrefix helper that only normalizes the root system prefixes.
  2. Updated FileInfo.init in BuildFSSync.swift to stop attempting manual path resolution for symlinks, and instead directly extract the raw target string from the filesystem using FileManager.default.destinationOfSymbolicLink(atPath:).

This ensures the exact symlink structures are preserved in the tar payload sent to buildkit.

@svelez

svelez commented Jul 21, 2026

Copy link
Copy Markdown

Hey... just wanted to point out #1899 (comment)

Not sure if you would like to include that in this PR or if I should work on addressing independenly

Comment thread Sources/ContainerBuild/URL+Extensions.swift
Comment thread Makefile
Comment thread Sources/ContainerXPC/XPCClient.swift
@lakshitsoni26

Copy link
Copy Markdown
Author

Hey... just wanted to point out #1899 (comment)

Not sure if you would like to include that in this PR or if I should work on addressing independenly

I apologize for bundling these together! I will split this up. I'll revert the Makefile changes immediately, and I will separate the XPC Concurrency fix and the Symlink Context fix into two independent PRs so they are easier to review.

@lakshitsoni26

Copy link
Copy Markdown
Author

Hi @svelez and @jglogan, thank you both for the helpful feedback on this!

You are completely right—bundling these three unrelated changes into a single PR made this too difficult to review and caused unnecessary conflicts. To make your lives easier, I have completely split this work up:

  1. Symlink Context Resolution (Fixes [Bug]: container build ignores default/relative build context in mktemp directory, but works with absolute path #1899): I see this was recently resolved internally upstream, so I am dropping my commit for it here to avoid conflicts.
  2. XPC Concurrency Deadlock: I have extracted this into a clean, independent PR here: Fix XPCClient ContinuationResolver deadlock #1987
  3. Makefile Test Flags: I have extracted the SwiftPM flag updates into a clean, independent PR here: Update Makefile to use modern SwiftPM parallel test flags #1988

I am closing this bundled PR in favor of the clean ones above. Thanks again for the guidance on keeping PRs perfectly scoped!

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 build ignores default/relative build context in mktemp directory, but works with absolute path

3 participants