]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: checks: make sure fastinter is used even on forced transitions
authorWilly Tarreau <w@1wt.eu>
Tue, 6 Dec 2022 17:20:56 +0000 (18:20 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 6 Dec 2022 17:48:22 +0000 (18:48 +0100)
AurĂ©lien also found that while previous commit a56798ea4 ("BUG/MEDIUM:
checks: do not reschedule a possibly running task on state change")
addressed one specific case where the check's task had to be woken up
quickly, but it's not always sufficient as the check will not be
considered as expired regarding the fastinter yet.

Let's make sure we do consider this specific case to update the timer
based on the new state if the new value is shorter. This particularly
means that even if the timer is not expired yet during a wakeup when
nothing is in progress, we need to check if applying the currently
effective interval right now to the current date would expire earlier
than what is programmed, then the timer needs to be updated. I.e.
make sure we never miss fastinter during a state transition before
the end of the current period.

The approach is not pretty, but it forces to repass via the existing
block dedicated to updating the timer if the current one is expired
and the updated one would appear earlier.

This must be backported to 2.7 along with the commit above.

src/check.c

index e4f9756a34222be6737e8822e461829cebf9e49d..0f5202898a83fb6f5a357402d4a19e8c8b93c58d 100644 (file)
@@ -1138,8 +1138,21 @@ struct task *process_chk_conn(struct task *t, void *context, unsigned int state)
                TRACE_STATE("health-check state to purge", CHK_EV_TASK_WAKE, check);
        }
        else if (!(check->state & (CHK_ST_INPROGRESS))) {
-               /* no check currently running */
+               /* no check currently running, but we might have been woken up
+                * before the timer's expiration to update it according to a
+                * new state (e.g. fastinter), in which case we'll reprogram
+                * the new timer.
+                */
                if (!expired) /* woke up too early */ {
+                       if (check->server) {
+                               int new_exp = tick_add(now_ms, MS_TO_TICKS(srv_getinter(check)));
+
+                               if (tick_is_expired(new_exp, t->expire)) {
+                                       TRACE_STATE("health-check was advanced", CHK_EV_TASK_WAKE, check);
+                                       goto update_timer;
+                               }
+                       }
+
                        TRACE_STATE("health-check wake up too early", CHK_EV_TASK_WAKE, check);
                        goto out_unlock;
                }
@@ -1264,6 +1277,7 @@ struct task *process_chk_conn(struct task *t, void *context, unsigned int state)
        check->state &= ~(CHK_ST_INPROGRESS|CHK_ST_IN_ALLOC|CHK_ST_OUT_ALLOC);
        check->state |= CHK_ST_SLEEPING;
 
+ update_timer:
        if (check->server) {
                rv = 0;
                if (global.spread_checks > 0) {