Skip to content

Commit

Permalink
quic: don't block when closing read-only streams
Browse files Browse the repository at this point in the history
Stream.Close blocks until all data sent on a stream has been
acked by the peer. Don't block indefinitely when closing
a read-only stream, waiting for an ack of data we never sent.

For golang/go#58547

Change-Id: I4087666f739d7388e460b613d211c043626f1c87
Reviewed-on: https://go-review.googlesource.com/c/net/+/524038
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
  • Loading branch information
neild committed Aug 30, 2023
1 parent b4d09be commit 7374d34
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 1 deletion.
7 changes: 6 additions & 1 deletion internal/quic/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ func newStream(c *Conn, id streamID) *Stream {
inresetcode: -1, // -1 indicates no RESET_STREAM received
ingate: newLockedGate(),
outgate: newLockedGate(),
outdone: make(chan struct{}),
}
if !s.IsReadOnly() {
s.outdone = make(chan struct{})
}
return s
}
Expand Down Expand Up @@ -237,6 +239,9 @@ func (s *Stream) Close() error {
// CloseContext discards the buffer and returns the context error.
func (s *Stream) CloseContext(ctx context.Context) error {
s.CloseRead()
if s.IsReadOnly() {
return nil
}
s.CloseWrite()
// TODO: Return code from peer's RESET_STREAM frame?
return s.conn.waitOnDone(ctx, s.outdone)
Expand Down
11 changes: 11 additions & 0 deletions internal/quic/stream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,17 @@ func TestStreamCloseWaitsForAcks(t *testing.T) {
}
}

func TestStreamCloseReadOnly(t *testing.T) {
tc, s := newTestConnAndRemoteStream(t, serverSide, uniStream, permissiveTransportParameters)
if err := s.CloseContext(canceledContext()); err != nil {
t.Errorf("s.CloseContext() = %v, want nil", err)
}
tc.wantFrame("closed stream sends STOP_SENDING",
packetType1RTT, debugFrameStopSending{
id: s.id,
})
}

func TestStreamCloseUnblocked(t *testing.T) {
for _, test := range []struct {
name string
Expand Down

0 comments on commit 7374d34

Please sign in to comment.