From: Willy Tarreau Date: Fri, 5 Aug 2022 06:45:56 +0000 (+0200) Subject: BUG/MEDIUM: quic: break out of the loop in quic_lstnr_dghdlr X-Git-Tag: v2.7-dev3~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f9d4a7dad385d66edfab99c307bb1d493c3eff04;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: quic: break out of the loop in quic_lstnr_dghdlr The function processes packets sent by other threads in the current thread's queue. But if, for any reason, other threads write faster than the current one processes, this can lead to a situation where the function never returns. It seems that it might be what's happening in issue #1808, though unfortunately, this function is one of the rare without traces. But the amount of calls to functions like qc_lstnr_pkt_rcv() on a single thread seems to indicate this possibility. Thanks to Tristan for his efforts in collecting extremely precious traces! This likely needs to be backported to 2.6. --- diff --git a/src/quic_sock.c b/src/quic_sock.c index a2be5255f8..3eacb39f22 100644 --- a/src/quic_sock.c +++ b/src/quic_sock.c @@ -251,6 +251,7 @@ static int quic_lstnr_dgram_dispatch(unsigned char *buf, size_t len, void *owner LIST_APPEND(dgrams, &dgram->list); MT_LIST_APPEND(&quic_dghdlrs[cid_tid].dgrams, &dgram->mt_list); + /* typically quic_lstnr_dghdlr() */ tasklet_wakeup(quic_dghdlrs[cid_tid].task); return 1; diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 367a9a533b..564da9bf07 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -6572,6 +6572,7 @@ struct task *quic_lstnr_dghdlr(struct task *t, void *ctx, unsigned int state) struct quic_dgram *dgram; int first_pkt = 1; struct list *tasklist_head = NULL; + int max_dgrams = global.tune.maxpollevents; while ((dgram = MT_LIST_POP(&dghdlr->dgrams, typeof(dgram), mt_list))) { pos = dgram->buf; @@ -6606,10 +6607,18 @@ struct task *quic_lstnr_dghdlr(struct task *t, void *ctx, unsigned int state) /* Mark this datagram as consumed */ HA_ATOMIC_STORE(&dgram->buf, NULL); + + if (--max_dgrams <= 0) + goto stop_here; } return t; + stop_here: + /* too much work done at once, come back here later */ + if (!MT_LIST_ISEMPTY(&dghdlr->dgrams)) + tasklet_wakeup((struct tasklet *)t); + err: return t; }