test(next): the run loop guard never holds the XCTest leg's main loop (signal-6 abort on some fleet Macs)
What is wrong
On some fleet Macs, every CmuxNext suite step reads as failed even though all of its Swift Testing tests pass. swift test --filter X first runs the XCTest leg (xctest -XCTest '' CmuxNextPackageTests.xctest), and that leg dies on signal 6 about 650 s in, before any test starts:
cmux-next test process: holding the main run loop open so a stray stop cannot end this test run (0)
xctest[...] Error obtaining permanent ID: ... "The model configuration used to open the store is incompatible ..."
error: Process '.../xctest -XCTest '' .../CmuxNextPackageTests.xctest' exited with unexpected signal code 6
The leg runs no case: this package has no XCTestCase, so no XCTest case aborts. On a healthy worker the leg prints Executed 0 tests within a second.
It aborts on base commits too, not just on PR heads:
- base
7fd513eaa73eed7bba6a6400724f608b1b6dcb27(feat-cmux-next): fleet step 0dff75c03c95925a5f79b446 83ba468(base plus one test file and nothing else): step 2c8b77668d07787212926acb- PR heads
cea57c4and191b5ab: steps c37127f6dd9caeae8f192a3b (4 of 4 suites) and 58b12f0c6091774c1f030a1e
That makes three different Macs. Two other Macs ran the same suites without it.
Cause
The guard comes from #25861 (CmuxNextTestRunLoopGuard.c). It queues a block on the main run loop that takes the main thread for good, so a stray CFRunLoopStop cannot end Swift Testing's drain-queue run. Its constructor also runs in the XCTest leg, but there is no drain queue there: XCTest's runner is synchronous on the main thread.
On the affected hosts the leg turns the main run loop once while it loads (a Contacts store XPC wait, which is the Error obtaining permanent ID line). The queued block runs then, which is the "holding" line inside the XCTest leg, and the leg never gets the thread back. On healthy workers nothing turns the loop, and that leg prints no "holding" line.
Fix
The guard does not hold in a process whose argv has -XCTest. The Swift Testing process (swiftpm-testing-helper) is unchanged, so the guard still protects the runs it was added for.
Risk
risk:low. Test-support C only; no app code.
Evidence
The same step (CmdWTargetTests), pinned to the same affected Mac:
- at base
7fd513e: step 0dff75c03c95925a5f79b446. The XCTest leg prints "holding", then aborts with signal 6, and the step fails after 666 s. - at this change (
827a7ba, identical to this head apart from a comment): step 067b71fe04431afa6bf92795. The XCTest leg printsExecuted 0 testswith no "holding" line, the Swift Testing leg holds as before, and the suite passes in 10 s.
Review: router-review: SHIP at e741ba53cdf88c85cd1028cf306af6b594004044 (gpt-6-astra high), Follow-ups: none.
Performance
| metric | before | after | delta | harness or run link |
|---|---|---|---|---|
CmdWTargetTests suite step on an affected Mac, wall time | 666 s, signal 6 (failed) | 10 s, passed | -656 s | fleet steps 0dff75c03c95925a5f79b446 / 067b71fe04431afa6bf92795 |
Changelog
none
Agent session: agent session
š¤ Generated with Claude Code