[LEAPSECS] any other parties?
dennis.c.ferguson at gmail.com
Mon Jul 9 16:09:09 EDT 2012
On 9 Jul, 2012, at 08:51 , Zefram wrote:
> Nero Imhard wrote:
>> Is that really the Unix way? I always thought that "proper"
>> implementations didn't step back, but paused the time for a second at
>> :59:59 (while still having subsequent calls of gettimeofday return
>> increasing values by adding microseconds as needed).
A very long time ago (more than a quarter century) BSD Unix kernels
had code in the kernel's time-reading logic which would record the
time returned each time the clock was read, and which would ensure
that a subsequent call to get the time would return a time at least
one microsecond later than that returned previously. This code
existed to cover up flaws in how the system extrapolated times between
clock interrupts and in the implementation of adjtime(2), which otherwise
would cause the clock to return times that did not always move forward.
The original ntpd implementation running on those systems handled leap
seconds by attempting to set the clock back one second, as close to :00:00
as it could arrange, by a call to settimeofday(2). settimeofday(2) had
the side effect of resetting the internal variable holding the last time
returned, so the backward time step the leap was implemented with was
visible to time consumers. When they moved the leap second support
into the kernel with the RFC 1305 interface, however, they apparently
did the one second step back without resetting the internal variable,
with the result that the step back was not as visible to consumers and
the time returned to system calls would get stuck somewhere between
59:59 and 00:00 (depending on the time the last clock read before the
leap had returned) for at least part of the second. Doing this, and
documenting it as working that way, effectively turned a slightly
tacky hack around a constrained and flawed clock implementation into
I would hope most systems have not retained this behavior. Modern
computers have much better hardware time sources, allowing an implementation
to avoid the flaws that prompted the original hack, and demanding that
time-reading system calls write the time returned into a shared variable
is a distinctly SMP-unfriendly way to implement a function which
otherwise could be done read-only and lock-free.
> POSIX implies that the :59:60 second appears identical to the :00:00
> second; i.e., the clock steps back at the end of the leap second.
> The NTP model (and practice of some implementations) says that the clock
> should step back at the start of the leap second, making the :59:60
> second appear identical to the :59:59 second. In either case, if you
> look only at the integer seconds portion of the clock then you could
> interpret it as "paused", in that you get the same time_t value for a
> period of two seconds rather than the usual one, while the time_t value
> monotonically increased throughout. But if you look at the microseconds
> from gettimeofday, you see the microseconds values [0,1000000) occur
> twice in succession, depicting a repeat of a second rather than a pause
> or an extra-long second.
ntpd (with the ntp_adjtime(2) system call implemented) did indeed cause
the system clock to pause, both the seconds and microseconds, during a
leap second. Prof. Mills's most recent book, which is only a few years
old, still documents it as working this way, though there is enough wrong
with doing this that many systems may not do that any more (I hope). As
ntpd essentially takes kernel timestamps and shoves them into packets,
this behavior was also detectable by ntpd neighbors
The unfortunate thing about the latter is that since ntpd the implementation
was a little sleazy and ambiguous about what happened during a leap second,
NTP, the on-the-wire protocol definition, was made similarly ambiguous. This
did not have to be (as I realized when working through what was necessary
to use standard NTP to keep non-POSIX "right" kernel time synchronized).
While NTP-on-the-wire might replay the :59:59 timestamps over you can
disambiguate which of these you are getting by noting that timestamps from
the first time through :59:59 will have the leap second warning set while
the timestamps from the second time through (i.e. the :59:60 timestamps) won't.
The only defect with this is that there are actually two timestamps in each
packet which require disambiguation, but only one leap second warning bit,
so while you can determine with certainty which :59:59 one of the timestamps
came from you still have to guess at the other. With a little bit more care
in defining the protocol this could have been fixed.
More information about the LEAPSECS