From: Willy Tarreau Date: Wed, 7 Sep 2011 19:33:14 +0000 (+0200) Subject: [BUG] peers: ensure the peers are resumed if they were paused X-Git-Tag: v1.5-dev8~117 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c03ebbfca481687bfe04b12db064d89aedb6f4d7;p=thirdparty%2Fhaproxy.git [BUG] peers: ensure the peers are resumed if they were paused Upon an incoming soft restart request, we first pause all frontends and peers. If the caller changes its mind and asks us to resume (eg: failed binding), we must resume all the frontends and peers. Unfortunately the peers were not resumed. The code was arranged to avoid code duplication (which used to hide the issue till now). --- diff --git a/src/proxy.c b/src/proxy.c index 2000fd3b32..14e37eb93f 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -668,6 +668,55 @@ void stop_proxy(struct proxy *p) p->state = PR_STSTOPPED; } +/* This function resumes listening on the specified proxy. It scans all of its + * listeners and tries to enable them all. If any of them fails, the proxy is + * put back to the paused state. It returns 1 upon success, or zero if an error + * is encountered. + */ +int resume_proxy(struct proxy *p) +{ + struct listener *l; + int fail; + + if (p->state != PR_STPAUSED) + return 1; + + Warning("Enabling %s %s.\n", proxy_cap_str(p->cap), p->id); + send_log(p, LOG_WARNING, "Enabling %s %s.\n", proxy_cap_str(p->cap), p->id); + + fail = 0; + for (l = p->listen; l != NULL; l = l->next) { + if (!resume_listener(l)) { + int port; + + port = get_host_port(&l->addr); + if (port) { + Warning("Port %d busy while trying to enable %s %s.\n", + port, proxy_cap_str(p->cap), p->id); + send_log(p, LOG_WARNING, "Port %d busy while trying to enable %s %s.\n", + port, proxy_cap_str(p->cap), p->id); + } + else { + Warning("Bind on socket %d busy while trying to enable %s %s.\n", + l->luid, proxy_cap_str(p->cap), p->id); + send_log(p, LOG_WARNING, "Bind on socket %d busy while trying to enable %s %s.\n", + l->luid, proxy_cap_str(p->cap), p->id); + } + + /* Another port might have been enabled. Let's stop everything. */ + fail = 1; + break; + } + } + + p->state = PR_STREADY; + if (fail) { + pause_proxy(p); + return 0; + } + return 1; +} + /* * This function temporarily disables listening so that another new instance * can start listening. It is designed to be called upon reception of a @@ -710,48 +759,29 @@ void pause_proxies(void) */ void resume_proxies(void) { + int err; struct proxy *p; - struct listener *l; - int fail; + struct peers *prs; + err = 0; p = proxy; tv_update_date(0,1); /* else, the old time before select will be used */ while (p) { - if (p->state == PR_STPAUSED) { - Warning("Enabling %s %s.\n", proxy_cap_str(p->cap), p->id); - send_log(p, LOG_WARNING, "Enabling %s %s.\n", proxy_cap_str(p->cap), p->id); - - fail = 0; - for (l = p->listen; l != NULL; l = l->next) { - if (!resume_listener(l)) { - int port; - - port = get_host_port(&l->addr); - if (port) { - Warning("Port %d busy while trying to enable %s %s.\n", - port, proxy_cap_str(p->cap), p->id); - send_log(p, LOG_WARNING, "Port %d busy while trying to enable %s %s.\n", - port, proxy_cap_str(p->cap), p->id); - } - else { - Warning("Bind on socket %d busy while trying to enable %s %s.\n", - l->luid, proxy_cap_str(p->cap), p->id); - send_log(p, LOG_WARNING, "Bind on socket %d busy while trying to enable %s %s.\n", - l->luid, proxy_cap_str(p->cap), p->id); - } - - /* Another port might have been enabled. Let's stop everything. */ - fail = 1; - break; - } - } - - p->state = PR_STREADY; - if (fail) - pause_proxy(p); - } + err |= !resume_proxy(p); p = p->next; } + + prs = peers; + while (prs) { + p = prs->peers_fe; + err |= !resume_proxy(p); + prs = prs->next; + } + + if (err) { + Warning("Some proxies refused to resume, a restart is probably needed to resume safe operations.\n"); + send_log(p, LOG_WARNING, "Some proxies refused to resume, a restart is probably needed to resume safe operations.\n"); + } } /* Set current session's backend to . Nothing is done if the