On 07/01/2015 08:40, Paul Jarc wrote:
I'm finally digging into a long-standing bug exhibited by runwhen (rw-match computes a timestamp 10 seconds too early), and I think the problem is in skalibs. tai_from_sysclock() adds 10 seconds depending on whether skalibs is configured with --enable-tai-clock. But tai_from_timeval doesn't, so they're inconsistent.
Actually, they're not; what is inconsistent is the naming. I probably should have paid more attention to that, and may change it in the future (yay API changes). In "tai_from_sysclock", "tai" means: what will be stored in that structure is a real, absolute TAI time. It's the TAI time corresponding to the sysclock time. It's the same whether the clock is TAI-10 (in which case you simply add 10 seconds) or whether it's UTC (in which case you add 10 seconds plus the leap seconds). The tai_from_utc function, which tai_from_sysclock resolves to when --enable-tai-clock is not given, does add the 10 seconds too. In "tai_from_timeval", "tai" means: store the same information in a tai_t. It's a simple format conversion function - the struct timeval could hold anything, a TAI-10 time, a UTC time, or something else, as long as it's absolute. No time conversion operation is done here. Yes, it's confusing. My bad.
actually both wrong: the correct behavior for both should be to unconditionally add 10 seconds, and conditionally add leap seconds depending on --enable-tai-clock
That is what happens for tai_from_sysclock. That is not what happens for tai_from_timeval, on purpose. I suspect your problem in runwhen is that you are calling tai_from_timeval(), or any other simple format conversion function, while expecting a time conversion function. You should always be using tain_now() to get the current time, it will give you TAI no matter what your setup is. You should not generally use tai_from_timeval() yourself.
With a POSIX clock and no --enable-tai-clock, we need to add the appropriate amount of leap seconds or else the tai_t values we generate will differ from those simultaneously generated on a system using TAI-10 and --enable-tai-clock.
Yes, that is exactly what happens. When you call tai_sysclock(), the TAI value you get is the same whether your clock is set to TAI-10 and you have --enable-tai-clock, or your clock is set to UTC and you have --disable-tai-clock. The tain_sysclock() function, which is what tain_now() normally calls (unless you asked --enable-monotonic), goes like this: * sysclock_get() gets the time from the system clock, no matter its format, into a tain_t. tain_from_timespec or tain_from_timeval are just struct conversions, they're time-agnostic. * tai_from_sysclock() assumes that the time it is given comes directly from the system clock in its native format, and converts it into TAI: - by adding 10 seconds if the system clock is TAI-10 - by calling tai_from_utc() otherwise + tai_from_utc() adds 10 seconds plus the leap seconds so what you get in the end is always TAI.
(This means that on a POSIX system, converting future times to TAI will give you wrong results after the time when the as-yet-unknown next leap second will be added.)
That's unfortunately unavoidable, and a limitation of POSIX. Time arithmetic can only be performed correctly with linear time, which TAI is and UTC is not. That is why skalibs uses TAI for all its time computations. But with a UTC clock, you do need an accurate leap second table to make the correct conversions, and if you're computing past the last known leap second, tough luck. The alternative with a UTC clock, which basically every non-skalibs- based system uses, is to perform time arithmetic with UTC, which gives you wrong results whether far into the future or not, and they simply don't care because "it would be too hard". Thanks POSIX. -- Laurent