Gather a run's files where they can be swept - #873
Open
MayCXC wants to merge 8 commits into
Open
Conversation
The reaper that runs at a concurrency of one deletes everything in the test directory except the unpacked rootfs it means to preserve. It held that rootfs path as FileManager reports it, under /var, and compared it against the entries of contentsOfDirectory, which reports them under /private/var, so the preserved path never matched any entry and the rootfs was deleted along with the per-test files. The unpack coordinator still held it as unpacked, so the next test opened a rootfs that was no longer there and failed with a missing file error. Resolve both sides with resolvingSymlinksInPathWithPrivate, which exists for this difference between the two views of the same directory.
Tests guarded for Linux are compiled out on macOS, so `make test` reports success without having run them, and nothing says so. The target that does run them is not mentioned anywhere outside the makefile.
The default kernel the tests fetch had drifted from the one users run. container installs kata 3.28.0 and its 6.18.15 kernel, while these tests fetched 3.17.0, so the suite exercised a guest with a different feature set to the one it is meant to represent. Nested runtimes are the visible case: 3.17.0 was built without nf_tables, so a docker daemon inside a container fails there and works on what ships. Kata moved from xz to zstd between those releases, so the archive is no longer named for its compression and tar is left to recognise it rather than being told, which also holds if the format changes again.
A test's rootfs clones, init block, and writable layers land in a directory the runner creates for it and deletes when it finishes, so a test holds disk only while it runs at any concurrency. The run-shared directory holds the unpacked images every bootstrap clones from, and is removed when the run ends.
A container's storage is its rootfs, an optional writable layer, and its mounts; a machine's is its containers' plus the volumes they share. One generic shape describes both the Mount values a machine is configured with and the AttachedFilesystem values it reports once attached, so converting between the two is a map over the structure and the roles cannot drift between configuration and attachment. Device addresses are allocated walking the same sorted order the devices are created in, on both backends. Consumers read roles instead of list positions: the spec builders take a container's mounts without prefix arithmetic, pod volumes mount by name, and a cloud-hypervisor volume's virtiofsd is held by a machine-lifetime reference alongside its containers' reference counts.
A test that wants a directory of its own asks for a temporary one, and none of the thirty four places that do take it away again, so a run left one behind for every test that asked and every run added more. The suite already removes its own directory when it finishes, so pointing the temporary directory at that one puts them somewhere already reached, and takes any a test adds later with them.
A run took a name of its own among the system's temporary files, so anything it left behind could only be found by knowing which run had left it, and nothing in the project could clean it. Runs gather under one directory now, which a make target sweeps the way the content one sweeps the image store. A run takes its own files away as it goes, so the target is for what an interrupted run, or one asked to keep them, has left.
The Linux dev container has no home directory that survives a run, so the imageStore it fills sits beside the repository and is bind mounted into place. That makes it the same content the macOS side keeps under its own home, held somewhere else only because the container cannot keep it. Cleaning the content took away one of them and left the other, so a tree asked to give up its content still held a store of images.
MayCXC
force-pushed
the
fix-integration-reaper
branch
from
August 27, 2026 20:47
d2d6967 to
3e7dda4
Compare
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
A run took a name of its own among the system's temporary files, so anything it left behind could only be found by knowing which run had left it, and nothing in the project could clean it. Runs gather under one directory now, which a make target sweeps the way the content one sweeps the image store.
A run takes its own files away as it goes, so the target is for what an interrupted run, or one asked to keep them, has left. The content the Linux dev container keeps beside the repository is cleaned with the one under the home directory.
Dependency and Merge Order
This targets stock
apple/containerization:mainand depends on #872, which in turn depends on #863. Merge order: #863, then #872, then this.The head carries both prerequisites' commits, because all three target stock
main. After they merge, this branch takes currentmainand its remaining diff is the run-directory gathering and the sweep target.Motivation and Context
The failure this addresses is quiet: a run that dies partway leaves its scratch files under a unique name in the system temporary directory, where nothing will ever collect them, and the next person to notice is whoever runs out of disk. Naming the directory after the project rather than after the run is what makes a sweep target possible at all.
Testing
swift buildandmake checkclean.swift test: 603 tests in 83 suites passed.make cleantestsremoves what an interrupted run leaves, and a completed run leaves nothing for it to do.Type of Change