]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: resolvers: Don't wait periodic resolution on healthcheck failure
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 24 Oct 2022 06:59:59 +0000 (08:59 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 16 Nov 2022 08:27:09 +0000 (09:27 +0100)
DNS resoltions may be triggered via a "do-resolve" action or when a connection
failure is experienced during a healthcheck. Cached valid responses are used, if
possible. But if the entry is expired or if there is no valid response, a new
reolution should be performed. However, an resolution is only performed if the
"resolve" timeout is expired. Thus, when this comes from a healthcheck, it means
no extra resolution is performed at all.

Now, when the resolution is performed for a server (SRV or SRVEQ) and no valid
response is found, the resolution timer is reset (last_resolution is set to
TICK_ETERNITY). Of course, it is only performed if no resolution is already
running.

Note that this feature was broken 5 years ago when the resolvers code was
refactored (67957bd59e).

This patch should fix the issue #1906. It affects all stable versions. However,
it is probably a good idea to not backport it too far (2.6, maybe 2.4) and with
some delay.

src/resolvers.c

index 4bbc6e50b3d8892e0c3ecec41318ae42ee6e570e..d93078003b392fba682e0efee829161891aac0cf 100644 (file)
@@ -460,8 +460,17 @@ void resolv_trigger_resolution(struct resolv_requester *req)
         * valid */
        exp = tick_add(res->last_resolution, resolvers->hold.valid);
        if (resolvers->t && (res->status != RSLV_STATUS_VALID ||
-           !tick_isset(res->last_resolution) || tick_is_expired(exp, now_ms)))
+           !tick_isset(res->last_resolution) || tick_is_expired(exp, now_ms))) {
+               /* If the resolution is not running and the requester is a
+                * server, reset the resoltion timer to force a quick
+                * resolution.
+                */
+               if (res->step == RSLV_STEP_NONE &&
+                   (obj_type(req->owner) == OBJ_TYPE_SERVER ||
+                    obj_type(req->owner) == OBJ_TYPE_SRVRQ))
+                       res->last_resolution = TICK_ETERNITY;
                task_wakeup(resolvers->t, TASK_WOKEN_OTHER);
+       }
 
        leave_resolver_code();
 }