Skip to content

Fix launchctl bootstrap failures being discarded as XPC errors - #2045

Draft
rogerneal wants to merge 1 commit into
apple:mainfrom
rogerneal:fix/2008-launchctl-bootstrap-errors
Draft

Fix launchctl bootstrap failures being discarded as XPC errors#2045
rogerneal wants to merge 1 commit into
apple:mainfrom
rogerneal:fix/2008-launchctl-bootstrap-errors

Conversation

@rogerneal

@rogerneal rogerneal commented Jul 30, 2026

Copy link
Copy Markdown

Summary

  • Surface launchctl bootstrap exit status and stderr from ServiceManager.register instead of continuing into a misleading apiserver XPC error.
  • When running as root (euid == 0) outside an Aqua session, bootstrap into the system domain instead of user/0 or gui/0.
  • Keep container system start idempotent when the service is already registered.
  • Add unit tests for domain selection and a real launchctl failure path for error surfacing.

Fixes #2008

Test plan

Tested

  • swift test --filter ServiceManagerTests (domain selection cases)
  • Real launchctl failure via ServiceManager.register with a missing plist; error includes launchctl bootstrap and status
  • Local Aqua bin/container system start --app-root ...: register() loaded com.apple.container.apiserver into gui/<uid> and the process started

Not tested

  • Exact GitHub Actions macos-26 reproduction: sudo container system start in a Background / non-login session
  • End-to-end healthy XPC ping / container system status after start in that CI environment
  • Passwordless/sudo launchctl bootstrap system on this developer machine (not available in the local session used for this PR)

Suggested CI verification

On a macos-26 runner:

  1. Install or build this branch
  2. Run sudo container system start --enable-kernel-install
  3. Confirm start succeeds without XPC connection error: Connection invalid
  4. Run container system status (or another command that talks to the apiserver)

@singhible

Copy link
Copy Markdown

Thanks for picking this up @rogerneal, and for being clear about what you did and
did not test. That made this easy to review.

I checked out f8d17d2 on macOS 26.5.2, Aqua session, non root. Your
ServiceManagerTests pass 7/7, PluginLoaderTest passes 12/12 twice in a row,
and swift format lint --strict is clean on both files. I could not reproduce the
non login root case either.

Three things I would raise:

The commit is unsigned. pr-build.yml runs a verify-signatures job that
fails on any unverified commit, so nothing can go green until that is fixed.

I would split the domain change out. The issue proposes two fixes, and this PR
does both. Surfacing the bootstrap failure is small and provable in any session
type. Bootstrapping into system moves where the services live, neither of us can
verify it, and it overlaps
#1514. Splitting lets the first
half merge on its own evidence instead of waiting for a macos-26 runner.

If the domain change stays, the rest of the code may not agree with it.
SystemStatus.swift:74 and SystemStop.swift:99 both call launchctl list
without a domain target, so they resolve against the calling process's launchd
context rather than the system domain you bootstrapped into. Your own idempotency
fallback goes through isRegistered, so it has the same question. If they do not
line up, a second system start throws instead of being a no op and
system status reports unregistered for a service that is running. Worth
confirming on the runner.

Two small ones while I am here: try isRegistered(...) inside the guard will
replace your good error message with a spawn error if launchctl cannot start, so
try? is safer, and LaunchPlist.CodingKeys.label.rawValue already exists
instead of the hardcoded "Label".

I think the core idea is okay, and it matches what enumerate() in the same type
already does.

Surface launchctl exit status and stderr from ServiceManager.register
instead of continuing into a misleading apiserver XPC error. Keep
container system start idempotent when the service is already registered.

The system-domain bootstrap change for root outside Aqua is intentionally
left to a follow-up so this can merge on its own evidence.

Fixes apple#2008
@cursor
cursor Bot force-pushed the fix/2008-launchctl-bootstrap-errors branch from f8d17d2 to cde7f88 Compare August 2, 2026 02:14
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 system start discards launchctl bootstrap failures, yielding a misleading XPC error in non-login (CI) sessions

2 participants