From: Christopher Faulet Date: Mon, 8 Jul 2024 17:17:34 +0000 (+0200) Subject: MINOR: mux-spop: Use a dedicated function to update the SPOP connection timeout X-Git-Tag: v3.1-dev4~70 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=078f9d3583eb1373d1b6af9a5fabeec5884a7d25;p=thirdparty%2Fhaproxy.git MINOR: mux-spop: Use a dedicated function to update the SPOP connection timeout Force the SPOP servers to use the SPOE engine identifier as pool connection name. This way, idle SPOP connections, once implemented, of different engine but using the same backend will not be mixed up. The related issue is #2502. --- diff --git a/src/mux_spop.c b/src/mux_spop.c index 83616d9268..5e6a733175 100644 --- a/src/mux_spop.c +++ b/src/mux_spop.c @@ -827,13 +827,15 @@ static inline int spop_conn_is_dead(struct spop_conn *spop_conn) } /* update spop_conn timeout if needed */ -static __maybe_unused void spop_conn_update_timeout(struct spop_conn *spop_conn) +static void spop_conn_update_timeout(struct spop_conn *spop_conn) { - TRACE_ENTER(SPOP_EV_SPOP_CONN_WAKE, spop_conn->conn); + int is_idle_conn = 0; if (!spop_conn->task) goto leave; + TRACE_ENTER(SPOP_EV_SPOP_CONN_WAKE, spop_conn->conn); + if (spop_conn_may_expire(spop_conn)) { /* no more streams attached */ if (br_data(spop_conn->mbuf)) { @@ -846,6 +848,7 @@ static __maybe_unused void spop_conn_update_timeout(struct spop_conn *spop_conn) int exp = tick_add_ifset(now_ms, spop_conn->shut_timeout); spop_conn->task->expire = tick_first(spop_conn->task->expire, exp); + is_idle_conn = 1; } /* if a timeout above was not set, fall back to the default one */ @@ -853,13 +856,41 @@ static __maybe_unused void spop_conn_update_timeout(struct spop_conn *spop_conn) spop_conn->task->expire = tick_add_ifset(now_ms, spop_conn->timeout); } - // TODO: handle close_spread for now, there is no idle connection + if ((spop_conn->proxy->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && + is_idle_conn && tick_isset(global.close_spread_end)) { + /* If a soft-stop is in progress and a close-spread-time + * is set, we want to spread idle connection closing roughly + * evenly across the defined window. This should only + * act on idle frontend connections. + * If the window end is already in the past, we wake the + * timeout task up immediately so that it can be closed. + */ + int remaining_window = tick_remain(now_ms, global.close_spread_end); + if (remaining_window) { + /* We don't need to reset the expire if it would + * already happen before the close window end. + */ + if (tick_isset(spop_conn->task->expire) && + tick_is_le(global.close_spread_end, spop_conn->task->expire)) { + /* Set an expire value shorter than the current value + * because the close spread window end comes earlier. + */ + spop_conn->task->expire = tick_add(now_ms, statistical_prng_range(remaining_window)); + } + } + else { + /* We are past the soft close window end, wake the timeout + * task up immediately. + */ + task_wakeup(spop_conn->task, TASK_WOKEN_TIMER); + } + } } else spop_conn->task->expire = TICK_ETERNITY; task_queue(spop_conn->task); + TRACE_LEAVE(SPOP_EV_SPOP_CONN_WAKE, spop_conn->conn, 0, 0, (size_t[]){spop_conn->task->expire}); leave: - TRACE_LEAVE(SPOP_EV_SPOP_CONN_WAKE); } /********************************************************/ @@ -2495,11 +2526,7 @@ static int spop_process(struct spop_conn *spop_conn) (!br_data(spop_conn->mbuf) && ((spop_conn->flags & SPOP_CF_MUX_BLOCK_ANY) || LIST_ISEMPTY(&spop_conn->send_list)))) spop_release_mbuf(spop_conn); - if (spop_conn->task) { - spop_conn->task->expire = tick_add(now_ms, (spop_conn->state == SPOP_CS_CLOSED ? spop_conn->shut_timeout : spop_conn->timeout)); - task_queue(spop_conn->task); - } - + spop_conn_update_timeout(spop_conn); spop_send(spop_conn); TRACE_LEAVE(SPOP_EV_SPOP_CONN_WAKE, conn); return 0; @@ -2810,8 +2837,7 @@ static void spop_detach(struct sedesc *sd) spop_release(spop_conn); } else if (spop_conn->task) { - spop_conn->task->expire = tick_add(now_ms, (spop_conn->state == SPOP_CS_CLOSED ? spop_conn->shut_timeout : spop_conn->timeout)); - task_queue(spop_conn->task); + spop_conn_update_timeout(spop_conn); TRACE_DEVEL("leaving, refreshing connection's timeout", SPOP_EV_STRM_END, spop_conn->conn); } else