From ea7797402756a7d6ea596f978dc13f7da88a839b Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Mon, 18 Dec 2017 22:24:22 +0700 Subject: [PATCH] don't send data that was queue before the stream write deadline expired --- send_stream.go | 5 ++++- send_stream_test.go | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/send_stream.go b/send_stream.go index 4b349030b..d82dee14d 100644 --- a/send_stream.go +++ b/send_stream.go @@ -92,10 +92,13 @@ func (s *sendStream) Write(p []byte) (int, error) { copy(s.dataForWriting, p) s.onData() + var bytesWritten int var err error for { + bytesWritten = len(p) - len(s.dataForWriting) deadline := s.writeDeadline if !deadline.IsZero() && !time.Now().Before(deadline) { + s.dataForWriting = nil err = errDeadline break } @@ -120,7 +123,7 @@ func (s *sendStream) Write(p []byte) (int, error) { } else if s.cancelWriteErr != nil { err = s.cancelWriteErr } - return len(p) - len(s.dataForWriting), err + return bytesWritten, err } // popStreamFrame returns the next STREAM frame that is supposed to be sent on this stream diff --git a/send_stream_test.go b/send_stream_test.go index f32cfb599..f8b77278c 100644 --- a/send_stream_test.go +++ b/send_stream_test.go @@ -245,6 +245,28 @@ var _ = Describe("Send Stream", func() { Expect(n).To(BeEquivalentTo(frame.DataLen())) }) + It("doesn't pop any data after the deadline expired", func() { + mockFC.EXPECT().SendWindowSize().Return(protocol.ByteCount(10000)).AnyTimes() + mockFC.EXPECT().AddBytesSent(gomock.Any()) + mockFC.EXPECT().IsNewlyBlocked() + deadline := time.Now().Add(scaleDuration(50 * time.Millisecond)) + str.SetWriteDeadline(deadline) + writeReturned := make(chan struct{}) + go func() { + defer GinkgoRecover() + _, err := strWithTimeout.Write(bytes.Repeat([]byte{0}, 100)) + Expect(err).To(MatchError(errDeadline)) + close(writeReturned) + }() + var frame *wire.StreamFrame + Eventually(func() *wire.StreamFrame { + frame = str.popStreamFrame(50) + return frame + }).ShouldNot(BeNil()) + Eventually(writeReturned, scaleDuration(80*time.Millisecond)).Should(BeClosed()) + Expect(str.popStreamFrame(50)).To(BeNil()) + }) + It("doesn't unblock if the deadline is changed before the first one expires", func() { deadline1 := time.Now().Add(scaleDuration(50 * time.Millisecond)) deadline2 := time.Now().Add(scaleDuration(100 * time.Millisecond))