Skip to content

Commit af30cef

Browse files
fix availability signaling of the send queue (quic-go#3597)
1 parent e496120 commit af30cef

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

send_queue.go

+7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ func newSendQueue(conn sendConn) sender {
3636
func (h *sendQueue) Send(p *packetBuffer) {
3737
select {
3838
case h.queue <- p:
39+
// clear available channel if we've reached capacity
40+
if len(h.queue) == sendQueueCapacity {
41+
select {
42+
case <-h.available:
43+
default:
44+
}
45+
}
3946
case <-h.runStopped:
4047
default:
4148
panic("sendQueue.Send would have blocked")

send_queue_test.go

+42
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,48 @@ var _ = Describe("Send Queue", func() {
7373
Eventually(done).Should(BeClosed())
7474
})
7575

76+
It("signals when sending is possible again, when the first write succeeded", func() {
77+
write := make(chan struct{}, 1)
78+
written := make(chan struct{}, 100)
79+
// now start sending out packets. This should free up queue space.
80+
c.EXPECT().Write(gomock.Any()).DoAndReturn(func(b []byte) error {
81+
<-write
82+
written <- struct{}{}
83+
return nil
84+
}).AnyTimes()
85+
// allow the first packet to be sent immediately
86+
write <- struct{}{}
87+
88+
done := make(chan struct{})
89+
go func() {
90+
defer GinkgoRecover()
91+
q.Run()
92+
close(done)
93+
}()
94+
95+
q.Send(getPacket([]byte("foobar")))
96+
<-written
97+
98+
// now fill up the send queue
99+
for i := 0; i < sendQueueCapacity+1; i++ {
100+
Expect(q.WouldBlock()).To(BeFalse())
101+
q.Send(getPacket([]byte("foobar")))
102+
}
103+
104+
Expect(q.WouldBlock()).To(BeTrue())
105+
Consistently(q.Available()).ShouldNot(Receive())
106+
write <- struct{}{}
107+
Eventually(q.Available()).Should(Receive())
108+
109+
// test shutdown
110+
for i := 0; i < sendQueueCapacity; i++ {
111+
write <- struct{}{}
112+
}
113+
114+
q.Close()
115+
Eventually(done).Should(BeClosed())
116+
})
117+
76118
It("does not block pending send after the queue has stopped running", func() {
77119
done := make(chan struct{})
78120
go func() {

0 commit comments

Comments
 (0)