Merge pull request #1047 from lucas-clemente/fix-1044

don't send data that was queue before the stream write deadline expired
This commit is contained in:
Marten Seemann
2017-12-20 11:43:38 +07:00
committed by GitHub
2 changed files with 26 additions and 1 deletions

View File

@@ -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

View File

@@ -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))