From 28360dc53f715c497fff822523f92769d8b1627d Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 7 Feb 2023 14:44:44 +0100 Subject: [PATCH] MEDIUM: clock: force internal time to wrap early after boot GH issue #2034 clearly indicates yet another case of time roll-over that went badly. Issues that happen only once every 50 days are hard to detect and debug, and are usually reported more or less synchronized from multiple sources. This patch finally does what had long been planned but never done yet, which is to force the time to wrap early after boot so that any such remaining issue can be spotted quicker. The margin delay here is 20s (it may be changed by setting BOOT_TIME_WRAP_SEC to another value). This value seems sufficient to permit failed health checks to succeed and traffic to come in and possibly start to update some time stamps (accept dates in logs, freq counters, stick-tables expiration dates etc). It could theoretically be helpful to have this in 2.7, but as can be seen with the two patches below, we've already had incorrect use cases of the internal monotonic time when the wall-clock one was needed, so we could expect to detect other ones in the future. Note that this will *not* induce bugs, it will only make them happen much faster (i.e. no need to wait for 50 days before seeing them). If it were to eventually be backported, these two previous patches must also be backported: BUG/MINOR: clock: use distinct wall-clock and monotonic start dates BUG/MEDIUM: cache: use the correct time reference when comparing dates --- include/haproxy/defaults.h | 4 ++++ src/clock.c | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/haproxy/defaults.h b/include/haproxy/defaults.h index 0882a9bbc3..f5f3b54595 100644 --- a/include/haproxy/defaults.h +++ b/include/haproxy/defaults.h @@ -202,6 +202,10 @@ #define TV_ETERNITY_MS (-1) #endif +/* delay between boot and first time wrap, in seconds */ +#ifndef BOOT_TIME_WRAP_SEC +#define BOOT_TIME_WRAP_SEC 20 +#endif /* we want to be able to detect time jumps. Fix the maximum wait time to a low * value so that we know the time has changed if we wait longer. */ diff --git a/src/clock.c b/src/clock.c index 75d2293ac9..59ec173c18 100644 --- a/src/clock.c +++ b/src/clock.c @@ -267,6 +267,16 @@ void clock_init_process_date(void) now = after_poll = before_poll = date; global_now = ((ullong)date.tv_sec << 32) + (uint)date.tv_usec; global_now_ms = now.tv_sec * 1000 + now.tv_usec / 1000; + + /* force time to wrap 20s after boot: we first compute the time offset + * that once applied to the wall-clock date will make the local time + * wrap in 5 seconds. This offset is applied to the process-wide time, + * and will be used to recompute the local time, both of which will + * match and continue from this shifted date. + */ + now_offset = (uint64_t)(-(global_now_ms / 1000U) - BOOT_TIME_WRAP_SEC) << 32; + global_now += now_offset; + th_ctx->idle_pct = 100; clock_update_date(0, 1); } -- 2.39.5