Skip to content

macOS guests 3/6: Darwin shared GuestService - #500

Draft
chruffins wants to merge 6 commits into
spike/macos-guestsfrom
feat/macos-guest-service
Draft

chruffins wants to merge 6 commits into
spike/macos-guestsfrom
feat/macos-guest-service

Conversation

@chruffins

@chruffins chruffins commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Stack

PR 3/6 of macOS guest integration; based on #498. Draft foundation for Darwin GuestService, readiness and networking. It does not depend on the OCI implementation in #499.

Implemented

  • Build the existing guest-agent for Darwin and reuse the shared gRPC GuestService on vsock 2222, including exec and file/stat RPCs. No permanent parallel prototype protocol.
  • Native Darwin AF_VSOCK listener with host-CID admission, close-on-exec descriptors and net.Conn deadlines; retain the existing Linux vsock listener.
  • Darwin orderly shutdown through the root-only OS command, with signal/privilege/cancellation validation instead of signaling launchd/PID 1.
  • Explicit Unimplemented for Darwin network identity reconfiguration; no NAT/static-IP/policy parity claim.
  • Honor exec stream cancellation; fix the empty-command shell default; stream non-TTY stdout/stderr in bounded chunks rather than buffering all command output.
  • Shared in-process gRPC tests for exec stdout/stderr/env/exit, output-before-exit, cancellation and file round-trips; Darwin shutdown policy and deadline tests.
  • Opt-in guest_agent image declaration enables normal exec/copy vsock paths and graceful-stop attempts; existing templates remain unmanaged and can explicitly disable integration.
  • Probe/persist system-agent readiness independently of macOS VMM-running state, without inventing Linux workload markers.
  • Cancel exec on WebSocket disconnect and stop resize forwarding when an exec session ends.

Validation

  • Full guest-agent package tests pass on Darwin with CGO enabled and disabled. The latter verifies native vsock is explicitly unavailable without CGO.
  • Linux/arm64 CGO-disabled guest-agent test executable cross-compiles; Linux test execution remains pending on an appropriate runner.
  • Focused host instance/API tests pass: macOS capability admission, request defaults/opt-out, readiness persistence/separation, existing boot-marker/state regressions and WebSocket disconnect cancellation.
  • Shared guest client/agent package tests pass.
  • Formatting/diff checks pass.
  • Independent automated review attempted but blocked by authentication 401; no clean independent-review claim.

Tests use an in-memory gRPC transport, temporary files and short-lived test commands. Shutdown policy tests stub the command: no actual host/guest shutdown, agent installation or live API deployment occurred.

Remaining draft gates

  • Live test-guest AF_VSOCK handshake and provisioning of the root LaunchDaemon.
  • Live normal API exec/files, readiness and graceful stop/teardown/recovery validation. Host integration is covered by focused tests, not a provisioned guest handshake.
  • Coordinate desktop session selection with Windows Add Windows guest control and ConPTY #431 rather than invent a conflicting proto extension.
  • Root/desktop handoff authorization, image provisioning and TCC/session permissions.
  • Broader PTY/backpressure/large-output, descendant-process cancellation, transfer failure/size and privilege/logging security tests.
  • Network capabilities/address observation; identity reconfiguration stays unsupported until implemented and validated.

No VM images, credentials, private notes or benchmark evidence are included. The live benchmark guest and its prototype agents remain untouched.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8f6dd1c. Configure here.

if err != nil {
return n, &net.OpError{Op: "read", Net: "vsock", Err: err}
}
return n, err

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read wraps EOF as OpError

Low Severity

vmConn.Read wraps every os.File.Read failure, including bare io.EOF, in net.OpError. Standard net.Conn implementations leave io.EOF unwrapped, and gRPC/HTTP2 compare with == io.EOF for a clean close. Guest disconnects can be treated as transport errors instead of orderly EOF.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8f6dd1c. Configure here.

chruffins and others added 4 commits October 9, 2026 14:45
- Persist macOS guest-agent readiness on the public read path by hydrating
  boot markers for macOS instances too.
- Kill the command's process group on cancellation or timeout so shell
  descendants do not outlive the command.
- Bound how long a cancelled exec waits for output to drain, so a client
  that stopped reading cannot hold the handler open.
- Hold the fork lock across Darwin vsock accept so an accepted descriptor
  is not inherited by a concurrent fork before it is marked close-on-exec.
The guest agent runs commands as root, as the Linux agent does, and the host
API is the only authorization boundary. Exec timeout ends the command; it
does not bound a healthy output stream.
@chruffins
chruffins force-pushed the feat/macos-guest-service branch from b2a5fae to a54ec4a Compare October 9, 2026 14:46
- Send the final exit code under the same bound as command output, so a
  client that stopped reading cannot hold the handler past a timeout.
- Kill the command's process group from the context rather than only through
  exec.Cmd.Cancel, which is not called once the direct child has exited.
- Make the drain bound a server field instead of a package variable, so tests
  do not mutate shared state read by handlers that outlive them.
Hydration and persistence duplicated the missing-marker checks, the serial
log parse, marker assignment and the readiness probe. Extract them into one
applyBootMarkers routine. Hydration keeps its scan throttling and rescan
bookkeeping; persistence keeps its save and metrics.

This branch has not been deployed

No deployments
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.

1 participant