From 67c4ac1d3ac79aabfe56e406f1b78f62f18c42de Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Thu, 8 Dec 2022 18:27:47 +1300 Subject: [PATCH] use a buffered channel in the acceptQueue (#53) There's a race condition here. A user might call Next to obtain the next stream, and get a nil result. He then calls Chan get notified about new incoming streams. If a new stream is accepted between the call to Next and the call to Chan, he won't be notified about that stream, unless the channel is buffered. --- session.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/session.go b/session.go index 961ef5c..95289ee 100644 --- a/session.go +++ b/session.go @@ -22,7 +22,10 @@ const closeWebtransportSessionCapsuleType http3.CapsuleType = 0x2843 type acceptQueue[T any] struct { mx sync.Mutex - c chan struct{} + // The channel is used to notify consumers (via Chan) about new incoming items. + // Needs to be buffered to preserve the notification if an item is enqueued + // between a call to Next and to Chan. + c chan struct{} // Contains all the streams waiting to be accepted. // There's no explicit limit to the length of the queue, but it is implicitly // limited by the stream flow control provided by QUIC. @@ -30,7 +33,7 @@ type acceptQueue[T any] struct { } func newAcceptQueue[T any]() *acceptQueue[T] { - return &acceptQueue[T]{c: make(chan struct{})} + return &acceptQueue[T]{c: make(chan struct{}, 1)} } func (q *acceptQueue[T]) Add(str T) {