Skip to content

Fix build context symlink resolution and XPC concurrency#1922

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

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.

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

1 participant