BUG/MEDIUM: resolvers: Properly stop server resolutions on soft-stop
When HAproxy is stopping, the DNS resolutions must be stopped, except those triggered from a "do-resolve" action. To do so, the resolutions themselves cannot be destroyed, the current design is too complex. However, it is possible to mute the resolvers tasks. The same is already performed with the health-checks. On soft-stop, the tasks are still running periodically but nothing if performed. For the resolvers, when the process is stopping, before running a resolution, we check all the requesters attached to this resolution. If t least a request is a stream or if there is a requester attached to a running proxy, a new resolution is triggered. Otherwise, we ignored the resolution. It will be evaluated again on the next wakeup. This way, "do-resolv" action are still working during soft-stop but other resoluation are stopped. Of course, it may be see as a feature and not a bug because it was never performed. But it is in fact not expected at all to still performing resolutions when HAProxy is stopping. In addution, a proxy option will be added to change this behavior. This patch partially fixes the issue #1874. It could be backported to 2.7 and maybe to 2.6. But no further. (cherry picked from commit 52ec6f14c4cbfe23cbe3bf6ef55af84ba17047de) Signed-off-by: Christopher Faulet <cfaulet@haproxy.com> (cherry picked from commit 058782b3f28d4ea6543f24d4996f97410f4e9f49) Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
This commit is contained in:
parent
883f35da4b
commit
b3c4d38aa8
@ -2394,6 +2394,48 @@ static struct task *process_resolvers(struct task *t, void *context, unsigned in
|
||||
|
||||
/* Handle all resolutions in the wait list */
|
||||
list_for_each_entry_safe(res, resback, &resolvers->resolutions.wait, list) {
|
||||
|
||||
if (unlikely(stopping)) {
|
||||
/* If haproxy is stopping, check if the resolution to know if it must be run or not.
|
||||
* If at least a requester is a stream (because of a do-resolv action) or if there
|
||||
* is a requester attached to a running proxy, the resolution is performed.
|
||||
* Otherwise, it is skipped for now.
|
||||
*/
|
||||
struct resolv_requester *req;
|
||||
int must_run = 0;
|
||||
|
||||
list_for_each_entry(req, &res->requesters, list) {
|
||||
struct proxy *px = NULL;
|
||||
|
||||
switch (obj_type(req->owner)) {
|
||||
case OBJ_TYPE_SERVER:
|
||||
px = __objt_server(req->owner)->proxy;
|
||||
break;
|
||||
case OBJ_TYPE_SRVRQ:
|
||||
px = __objt_resolv_srvrq(req->owner)->proxy;
|
||||
break;
|
||||
case OBJ_TYPE_STREAM:
|
||||
/* Always perform the resolution */
|
||||
must_run = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Perform the resolution if the proxy is not stopped or disabled */
|
||||
if (px && !(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)))
|
||||
must_run = 1;
|
||||
|
||||
if (must_run)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!must_run) {
|
||||
/* Skip the reolsution. reset it and wait for the next wakeup */
|
||||
resolv_reset_resolution(res);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (LIST_ISEMPTY(&res->requesters)) {
|
||||
abort_resolution(res);
|
||||
continue;
|
||||
|
Loading…
x
Reference in New Issue
Block a user