Skip to content

Don't let the boot-time ntpdate stall a VAX guest - #12

Merged
jacob-carlborg merged 1 commit into
masterfrom
claude/vax-bounded-ntpdate-wsrfrg
Aug 14, 2026
Merged

Don't let the boot-time ntpdate stall a VAX guest#12
jacob-carlborg merged 1 commit into
masterfrom
claude/vax-bounded-ntpdate-wsrfrg

Conversation

@jacob-carlborg

Copy link
Copy Markdown
Contributor

ntpdate's rc.d script runs ntpdate(8) inline, so everything after it in the boot sequence — sshd included — waits for it to return.

In CI a VAX guest sat at Setting date via ntp. for a full hour, never reached sshd, and failed Test Image (vax). It is not deterministic: the same commit passed on the next run.

Starting network.
Configuring network interfaces: qt0.
add net default: gateway 10.0.2.2
Waiting for duplicate address detection to finish...
Building databases: dev, utmp, utmpx, services.
Starting syslogd.
Setting date via ntp.          <- nothing further for 60 minutes

Four VAX jobs on the same commit, showing the coin flip — and that a healthy boot reaches sshd in ~2 minutes, not the ~15 the test's comment assumes:

run 10.1 11.0
31812267873 failed, wedged 60 min passed, 2m02s
31813765024 passed, 2m35s wedged

Why not just switch it off

That is what the QEMU ports do — configure_time_sync in resources/provision.sh sets ntpdate=NO, because QEMU seeds the emulated RTC from the host clock and the offset it would correct is already ~0.

That reasoning does not carry over. SIMH's KA655 has no battery-backed clock to seed: the kernel rejects what it reads and falls back to the file system time.

WARNING: preposterous TOD clock time
WARNING: using filesystem time
Fri Jan  1 12:20:21 UTC 2010

A VAX guest that never runs ntpdate boots years in the past, and every HTTPS fetch then fails on certificate validity instead. So it is kept, and bounded.

What bounds it

Neither of the two things in its path that can block indefinitely is bounded by ntpdate's own retries:

  • Resolving the pool names in the stock ntp.conf, which is what the rc.d script falls back to when ntpdate_hosts is empty. An unanswered DNS lookup has no deadline here at all, and is what wedged the guest. ntpdate_hosts takes precedence over ntp.conf, so numeric addresses keep DNS off the boot path entirely.
  • A server that accepts the query and never answers, which -t bounds — a worst case of a few seconds per address rather than forever.

The addresses are Cloudflare's time service, whose anycast addresses are documented as stable in a way a pool member's are not. ntpd still runs afterwards and corrects drift over the life of the VM, so they only have to be good enough for the initial step.

Scope

Branched from master and independent of #11: this is a pre-existing flake, not something that PR introduced, and the fix touches only the VAX provisioner, which #11 does not. It is worth having before the next release tag, though — Create Release runs after Test Image (vax), so a wedged VAX job fails the release job.


Generated by Claude Code

ntpdate's rc.d script runs ntpdate(8) inline, so everything after it in
the boot sequence -- sshd included -- waits for it to return. In CI a
VAX guest sat at "Setting date via ntp." for a full hour, never reached
sshd, and failed the image test; the same commit passed on the next run,
so it flips a coin.

The QEMU ports don't have this problem because provision.sh switches
ntpdate off outright: QEMU seeds the emulated RTC from the host clock,
so the offset it would correct is already ~0. That reasoning doesn't
carry over to SIMH, whose KA655 has no battery-backed clock to seed --
the kernel rejects what it reads ("preposterous TOD clock time") and
falls back to the file system time. A VAX guest that never runs ntpdate
boots years in the past, and every HTTPS fetch then fails on
certificate validity instead.

So keep it and bound it. Neither of the two things in its path that can
block indefinitely is bounded by ntpdate's own retries:

  - Resolving the pool names in the stock ntp.conf, which is what the
    rc.d script falls back to when ntpdate_hosts is empty. An
    unanswered DNS lookup has no deadline here at all, which is what
    wedged the guest. ntpdate_hosts takes precedence over ntp.conf, so
    numeric addresses keep DNS off the boot path entirely.
  - A server that accepts the query and never answers, which -t bounds.

The addresses are Cloudflare's time service, whose anycast addresses are
documented as stable in a way a pool member's are not. ntpd still runs
afterwards and corrects drift over the life of the VM, so they only have
to be good enough for the initial step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M9LHkNMNNfDf2Fa1ieGT8g
@jacob-carlborg
jacob-carlborg merged commit 67175e5 into master Aug 14, 2026
21 of 22 checks passed
jacob-carlborg pushed a commit that referenced this pull request Aug 14, 2026
Both sides added to the [Unreleased] changelog section. Keeps each: the
VAX ntpdate fix from master (#12) alongside this branch's entries, with
Fixed last, per Keep a Changelog's section order.
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.

2 participants