The previous commit
87cf2a6b ("BUG/MEDIUM: mux-h2: consider the send list
as pending data for the timeout") was incomplete: a stream blocked on the
connection window (H2_SF_BLK_MFCTL) may also be orphaned by h2_detach()
after its stream connector left, in which case it sits on the fctl_list
and not on the send_list. Nothing of its frame was emitted yet (typically
an ES/RST frame via a WANT_SHUTW, or the remaining fast-forward bytes of
its iobuf), so br_data() on the mux buffer can be zero.
Such a connection was still considered idle and, on a backend connection,
was armed with no timeout at all while not being reusable: the orphan is
still in streams_by_id so it is not moved to the idle list either. It
then relied on the peer to send a WINDOW_UPDATE to ever wake up, which a
stalled peer never does.
The blocked_list is deliberately not considered: streams blocked on their
own stream window (H2_SF_BLK_SFCTL) are never orphaned by h2_detach(), so
this list is always empty once the last stream connector detached.
This matches the original h2c_may_expire() from before commit
3439583dd
("MEDIUM: mux-h2: slightly relax timeout management rules") which
considered both lists. mux-fcgi is not affected, it has no flow-control
window and no fctl list.
This could be backported as far as 2.6, along with
87cf2a6b.
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
if (h2c_may_expire(h2c)) {
/* no more streams attached */
- if (br_data(h2c->mbuf) || !LIST_ISEMPTY(&h2c->send_list)) {
+ if (br_data(h2c->mbuf) || !LIST_ISEMPTY(&h2c->send_list) ||
+ !LIST_ISEMPTY(&h2c->fctl_list)) {
/* pending output data, or streams still queued to send
- * some (blocked on a missing mux buffer, their data
- * being still in their own iobuf): always the regular
- * data timeout.
+ * some (blocked on a missing mux buffer or on the
+ * connection window, their data or the frame to emit
+ * being still pending): always the regular data
+ * timeout.
*/
h2c->task->expire = tick_add_ifset(now_ms, h2c->timeout);
}