With "option idle-close-on-response", idle frontend connections must not be
closed during a soft-stop: haproxy waits for the next request and closes the
connection after responding to it, so that clients (or load balancers in
front of haproxy) don't send a request on a connection being
closed. h1_process() properly checks this option before closing an idle
connection when the proxy is stopping. But when "close-spread-time" is set,
h1_refresh_timeout() also considers idle frontend connections as candidates
to be closed during the spread window, without checking the option, and
shortens their timeout to a random point within the window. The timeout
task then silently closes them.
Let's not consider idle connections for the spread close when the option is
set, as done in h1_process().
This should be backported as far as 2.6.
/* idle front connections. */
h1c->task->expire = (tick_isset(h1c->idle_exp) ? h1c->idle_exp : tick_add_ifset(now_ms, h1c->timeout));
TRACE_DEVEL("refreshing connection's timeout (idle front h1c)", H1_EV_H1C_SEND|H1_EV_H1C_RECV, h1c->conn);
- is_idle_conn = 1;
+ /* With "option idle-close-on-response", idle connections
+ * must not be closed during a soft-stop, the next response
+ * will carry a "Connection: close" instead (see
+ * h1_process()).
+ */
+ if (!(h1c->px->options & PR_O_IDLE_CLOSE_RESP))
+ is_idle_conn = 1;
}
else if (!(h1c->flags & H1C_F_IS_BACK) && (h1c->state != H1_CS_RUNNING)) {
/* alive front connections waiting for a fully usable stream need a timeout. */