From b48e7c001658b06d98b4f52f45badde6eb062869 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 30 Mar 2021 18:13:26 +0200 Subject: [PATCH] BUG/MEDIUM: time: make sure to always initialize the global tick The issue with non-rotating freq counters was addressed in commit 8cc586c73 ("BUG/MEDIUM: freq_ctr/threads: use the global_now_ms variable") using the global date. But an issue remained with the comparison of the most recent time. Since the initial time in the structure is zero, the tick_is_lt() works on half of the periods depending on the first date an entry is touched. And the wrapping happened last night: $ date --date=@$(((($(date +%s) * 1000) & -0x8000000) / 1000)) Mon Mar 29 23:59:46 CEST 2021 So users of the last fix (backported to 2.3.8) may experience again an always increasing rate for the next 24 days if they restart their process. Let's always update the time if the latest date was not updated yet. It will likely be simplified once the function is reorganized but this will do the job for now. Note that since this timer is only used by freq counters, no other sub-system is affected. The bug can easily be tested with this config during the right time period (i.e. today to today+24 days + N*49.7 days): global stats socket /tmp/sock1 frontend web bind :8080 mode http http-request track-sc0 src stick-table type ip size 1m expire 1h store http_req_rate(2s) Issuing 'socat - /tmp/sock1 <<< "show table web"' should show a stable rate after 2 seconds. The fix must be backported to 2.3 and any other version the fix above goes into. Thanks to Thomas SIMON and Sander Klein for quickly reporting this issue with a working reproducer. --- src/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time.c b/src/time.c index 0cfc9bf3c8..fafe3720eb 100644 --- a/src/time.c +++ b/src/time.c @@ -268,7 +268,7 @@ void tv_update_date(int max_wait, int interrupted) old_now_ms = global_now_ms; do { new_now_ms = old_now_ms; - if (tick_is_lt(new_now_ms, now_ms)) + if (tick_is_lt(new_now_ms, now_ms) || !new_now_ms) new_now_ms = now_ms; } while (!_HA_ATOMIC_CAS(&global_now_ms, &old_now_ms, new_now_ms)); -- 2.39.5