]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: quic: break out of the loop in quic_lstnr_dghdlr
authorWilly Tarreau <w@1wt.eu>
Fri, 5 Aug 2022 06:45:56 +0000 (08:45 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 5 Aug 2022 14:12:00 +0000 (16:12 +0200)
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.

src/quic_sock.c
src/xprt_quic.c

index a2be5255f8543cbcb5ab8346c4e6c9857b478726..3eacb39f22d1d6a038c3445def3ea62a30dba1ee 100644 (file)
@@ -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;
index 367a9a533be782768af4de5fde96c9910dd2ceb4..564da9bf078d821e2f3f9cef1edef50917464982 100644 (file)
@@ -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;
 }