MINOR: mux-quic: correctly implement backend timeout

qcc_refresh_timeout() is the function called on QUIC MUX activity. Its
purpose is to update the timeout by selecting the correct value
depending on the connection state.

Prior to this patch, backend connections were mostly ignored by the
function. However, the default server timeout was selecting as a
fallback. This is incompatible with backend connections reuse.

This patch fixes timeout applied on backend connections. Only values
specific to frontend which are http-request and http-keep-alive timeouts
are now ignored for a backend connection. Also, fallback timeout is only
used for frontend connections.

This patch ensures that an idle backend connection won't be deleted due
to server timeout. This is necessary for proper connection reuse which
will be implemented in a future patch.
This commit is contained in:
Amaury Denoyelle 2025-07-22 15:44:17 +02:00
parent 95cb763cd6
commit 89329b147d

View File

@ -315,26 +315,26 @@ static void qcc_refresh_timeout(struct qcc *qcc)
goto leave; goto leave;
} }
/* Frontend timeout management /* Timeout management
* - detached streams with data left to send -> default timeout * - detached streams with data left to send -> default timeout
* - shutdown done -> timeout client-fin * - shutdown done -> timeout client-fin
* - stream waiting on incomplete request or no stream yet activated -> timeout http-request * - (FE only) stream waiting on incomplete request or no stream yet activated -> timeout http-request
* - idle after stream processing -> timeout http-keep-alive * - (FE only) idle after stream processing -> timeout http-keep-alive
* *
* If proxy stop-stop in progress, immediate or spread close will be * If proxy stop-stop in progress, immediate or spread close will be
* processed if shutdown already one or connection is idle. * processed if shutdown already one or connection is idle.
*/ */
if (!conn_is_back(qcc->conn)) { if (!LIST_ISEMPTY(&qcc->send_list) || !LIST_ISEMPTY(&qcc->tx.frms)) {
if (!LIST_ISEMPTY(&qcc->send_list) || !LIST_ISEMPTY(&qcc->tx.frms)) { TRACE_DEVEL("pending output data", QMUX_EV_QCC_WAKE, qcc->conn);
TRACE_DEVEL("pending output data", QMUX_EV_QCC_WAKE, qcc->conn); qcc->task->expire = tick_add_ifset(now_ms, qcc->timeout);
qcc->task->expire = tick_add_ifset(now_ms, qcc->timeout); }
} else if (qcc->app_st >= QCC_APP_ST_SHUT) {
else if (qcc->app_st >= QCC_APP_ST_SHUT) { TRACE_DEVEL("connection in closing", QMUX_EV_QCC_WAKE, qcc->conn);
TRACE_DEVEL("connection in closing", QMUX_EV_QCC_WAKE, qcc->conn); qcc->task->expire = tick_add_ifset(now_ms,
qcc->task->expire = tick_add_ifset(now_ms, qcc->shut_timeout);
qcc->shut_timeout); }
} else if (!conn_is_back(qcc->conn)) {
else if (!LIST_ISEMPTY(&qcc->opening_list) || unlikely(!qcc->largest_bidi_r)) { if (!LIST_ISEMPTY(&qcc->opening_list) || unlikely(!qcc->largest_bidi_r)) {
int timeout = px->timeout.httpreq; int timeout = px->timeout.httpreq;
struct qcs *qcs = NULL; struct qcs *qcs = NULL;
int base_time; int base_time;
@ -356,6 +356,12 @@ static void qcc_refresh_timeout(struct qcc *qcc)
TRACE_DEVEL("at least one request achieved but none currently in progress", QMUX_EV_QCC_WAKE, qcc->conn); TRACE_DEVEL("at least one request achieved but none currently in progress", QMUX_EV_QCC_WAKE, qcc->conn);
qcc->task->expire = tick_add_ifset(qcc->idle_start, timeout); qcc->task->expire = tick_add_ifset(qcc->idle_start, timeout);
} }
/* Fallback to client timeout if specific value not set. */
if (!tick_isset(qcc->task->expire)) {
TRACE_DEVEL("fallback to default timeout", QMUX_EV_QCC_WAKE, qcc->conn);
qcc->task->expire = tick_add_ifset(now_ms, qcc->timeout);
}
} }
/* If proxy soft-stop in progress and connection is inactive, /* If proxy soft-stop in progress and connection is inactive,
@ -392,14 +398,6 @@ static void qcc_refresh_timeout(struct qcc *qcc)
} }
} }
/* fallback to default timeout if frontend specific undefined or for
* backend connections.
*/
if (!tick_isset(qcc->task->expire)) {
TRACE_DEVEL("fallback to default timeout", QMUX_EV_QCC_WAKE, qcc->conn);
qcc->task->expire = tick_add_ifset(now_ms, qcc->timeout);
}
task_queue(qcc->task); task_queue(qcc->task);
leave: leave: