Host — the two remaining app-wide stall mechanisms plus main-thread pins
found by mining all nine hang reports:
- LinuxProcess.startStdinRelay wrote to a BLOCKING stdin fd on a
width-limited cooperative-pool thread, non-cancellably; wedged guests
starved the whole concurrency runtime (decode loops, watchdogs — an
app-wide freeze surviving the reconcile fix). Writes now offload to a
per-process GCD queue (vendored patch #18).
- TranscriptWriter (actor) did blocking write/fsync on the cooperative
pool; it now runs on its own DispatchSerialQueue executor.
- UserMessageBubble's truncation probe typeset entire pasted-log-sized
messages through CoreText per layout pass (100% main-thread pins in
the 07-21 hang reports); certainly-long messages now skip the probe
and render a prefix while collapsed.
- toolGroupSignature JSON-encoded every tool input in the transcript up
to 12.5x/s on the MainActor; now a structural hash. The summary pass
is trailing-throttled to 0.4s, and flatItems joins streaming chunks
once instead of re-copying the prefix per delta.
- StatusFeedFetcher.parseDate allocated three formatters per call (86%
of a pool thread in the 07-26 report); now shared statics.
Guest (vminitd) — teardown data loss and epoll registration hazards:
- IOPair no longer closes on a bare EPOLLHUP with a backpressure flush
in flight (dropped the CLI's final output line); EPOLLOUT finishes the
flush, then EOF closes loss-free. ManagedProcess.setExit closes only
stdin, letting stdout/stderr self-close on EOF, with an 8s grace pass
(patch #16).
- Epoll events carry a registration generation; the supervisor ignores
stale events for recycled fd numbers. registerFd refuses EEXIST
instead of clobbering the existing handler. TerminalIO's stdin relay
writes a dup of the terminal fd so its backpressure registration
can't collide with the stdout relay's (patch #17).
- VsockProxy flushes bytes parked toward the surviving peer on hangup,
closes the dialing socket on a failed backend connect, and
StandardIO/TerminalIO clean up partially-created pairs on setup
failure (patch #16).
Full suite: 1451+292+74+20 tests, two failures — both pre-existing
environmental (MacVM base image absent on this machine; a load-flaky
liveness test that passes 3/3 in isolation).
Co-Authored-By: Claude Fable 5 <[email protected]>
Switch the containerization dependency from the github URL to a vendored copy
(third_party/containerization, upstream commit 6b7b42ca) referenced by path, so
we can carry a small local patch that upstream lacks: LinuxContainer.Configuration
gains a `vmExtensions` field forwarded into VMConfiguration.extensions. Upstream
already supports VMConfiguration.extensions + the VZInstanceExtension hook, but
LinuxContainer — our only entry point — never forwarded them, so there was no way
to attach a device (e.g. a memory balloon) to a container's VM.
Tests/, docs/, examples/, images/ and the corresponding test targets are trimmed
for footprint (we never build the dependency's tests). See PATCHES.md for the full
diff vs. upstream and the re-vendoring procedure. Also adds the ContainerizationExtras
product to NucleicCore (AddressAllocator, named in the configureVZ signature).
Co-Authored-By: Claude Opus 4.8 <[email protected]>