fix(OSX timekeeping): self-manage timekeeping on OSX - #986
Conversation
📝 WalkthroughWalkthroughThe change replaces datagram-based guest time synchronization with an 8-byte timestamp stream, adds a macOS host sender over UDS/libkrun, and configures both sides to use port 7351 with retry, clock-jump detection, and stream-focused tests. ChangesHost time synchronization
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant HostClock
participant timekeep
participant libkrun
participant minimald
HostClock->>timekeep: detect heartbeat or clock jump
timekeep->>libkrun: write 8-byte timestamp to bridged socket
libkrun->>minimald: deliver timestamp over vsock stream
minimald->>minimald: decode frame and update CLOCK_REALTIME
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
crates/minvmd/src/timekeep.rs (1)
164-198: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winNo connect/write timeout — a wedged bridge can stall this thread indefinitely.
UnixStream::connectandwrite_all/flushhere have no deadline. If the kernel send buffer fills and the guest-side listener isn't reading (e.g. it's itself blocked — see the related comment onguest.rs'sread_exact), this dedicated thread can block pastTICK, delaying every later heartbeat/jump update. Consider a socket-level write/connect timeout (set_write_timeouton theUnixStream) as defense in depth alongside the guest-side fix.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/minvmd/src/timekeep.rs` around lines 164 - 198, Add a socket-level write timeout to the UnixStream created in the timekeeping loop before it is stored in conn, using a bounded duration appropriate for the TICK retry cadence; handle timeout-configuration failure consistently with connection setup. Ensure write_all and flush in the existing stream send path cannot block indefinitely, while preserving the current redial and retry behavior on errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/minimald/src/guest.rs`:
- Around line 690-705: Update serve_time_updates so each read_exact frame
operation is bounded by a tokio::time::timeout using a deadline of a few host
heartbeat intervals. Treat an elapsed timeout like UnexpectedEof by returning
Ok(()) so run_timekeep_listener can accept reconnects, while preserving existing
handling for successful reads, interruptions, and other I/O errors.
In `@crates/minvmd/src/timekeep.rs`:
- Around line 133-200: Update run’s scheduling state around due, jumped, and the
send result to track a pending jump-triggered update independently of last_sent.
Mark the jump update outstanding before attempting delivery, include that state
in the condition that bypasses the heartbeat, and clear it only after a
successful write/flush; retain it across connection failures so retries occur on
every TICK until delivery succeeds.
---
Nitpick comments:
In `@crates/minvmd/src/timekeep.rs`:
- Around line 164-198: Add a socket-level write timeout to the UnixStream
created in the timekeeping loop before it is stored in conn, using a bounded
duration appropriate for the TICK retry cadence; handle timeout-configuration
failure consistently with connection setup. Ensure write_all and flush in the
existing stream send path cannot block indefinitely, while preserving the
current redial and retry behavior on errors.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f13d57e8-f026-4649-865b-b858d48b4046
📒 Files selected for processing (5)
crates/minimald/src/guest.rscrates/minimald/src/main.rscrates/minvmd/src/cmd/vmm_child.rscrates/minvmd/src/lib.rscrates/minvmd/src/timekeep.rs
96fdd5d to
048ae24
Compare
Fixes: #985
The guest kernel has no TSI or virtio-vsock datagram implementation, so the libkrun-managed timekeeper isnt accessible. We run our own.
Summary by CodeRabbit
Note
Fix OSX timekeeping by self-managing host-to-guest clock sync over vsock
timekeepmodule incrates/minvmdthat runs a background sender thread on macOS, waking every 5s to detect clock jumps and sending heartbeats every 60s as 8-byte little-endian nanoseconds-since-epoch over a libkrun-bridged vsock stream (port 7351).crates/minimaldfrom a datagram socket on port 123 to a vsock stream server onTIMEKEEP_PORT(7351), reading 8-byte frames and callingclock_settimewhen drift exceeds threshold; idle connections are dropped after 300s.guest::TIMEKEEP_PORT.Macroscope summarized 048ae24.