diff --git a/send_queue.go b/send_queue.go index 8d9ec5ed..9d9260da 100644 --- a/send_queue.go +++ b/send_queue.go @@ -18,7 +18,10 @@ func newSendQueue(conn connection) *sendQueue { } func (h *sendQueue) Send(p *packetBuffer) { - h.queue <- p + select { + case h.queue <- p: + case <-h.runStopped: + } } func (h *sendQueue) Run() error { diff --git a/send_queue_test.go b/send_queue_test.go index 978a9dde..71c88129 100644 --- a/send_queue_test.go +++ b/send_queue_test.go @@ -1,6 +1,8 @@ package quic import ( + "errors" + "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -68,6 +70,31 @@ var _ = Describe("Send Queue", func() { Eventually(done).Should(BeClosed()) }) + It("does not block pending send after the queue has stopped running", func() { + done := make(chan struct{}) + go func() { + defer GinkgoRecover() + q.Run() + close(done) + }() + + // the run loop exits if there is a write error + testErr := errors.New("test error") + c.EXPECT().Write(gomock.Any()).Return(testErr) + q.Send(getPacket([]byte("foobar"))) + Eventually(done).Should(BeClosed()) + + sent := make(chan struct{}) + go func() { + defer GinkgoRecover() + q.Send(getPacket([]byte("raboof"))) + q.Send(getPacket([]byte("quux"))) + close(sent) + }() + + Eventually(sent).Should(BeClosed()) + }) + It("blocks Close() until the packet has been sent out", func() { written := make(chan []byte) c.EXPECT().Write(gomock.Any()).Do(func(p []byte) { written <- p })