mirror of
https://github.com/golang/net.git
synced 2026-03-31 02:17:08 +09:00
The http2 random write scheduler should not queue RST_STREAM frames with the DATA frames, and instead treat them as control frames. There can be deadlock situations if data frames block the queue, because if the sender wants to close the stream it sends an RST frame, but if the client is not draining the queue, the RST frame is stuck and the sender is not able to finish. Fixes golang/go#49741 Change-Id: I0940a76d1aad95f1c4d3856e4d79cf5ce2a78ff2 Reviewed-on: https://go-review.googlesource.com/c/net/+/367154 Trust: Dave Cheney <dave@cheney.net> Reviewed-by: Damien Neil <dneil@google.com> Trust: Damien Neil <dneil@google.com> Run-TryBot: Damien Neil <dneil@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
65 lines
1.8 KiB
Go
65 lines
1.8 KiB
Go
// Copyright 2016 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package http2
|
|
|
|
import "testing"
|
|
|
|
func TestRandomScheduler(t *testing.T) {
|
|
ws := NewRandomWriteScheduler()
|
|
ws.Push(makeWriteHeadersRequest(3))
|
|
ws.Push(makeWriteHeadersRequest(4))
|
|
ws.Push(makeWriteHeadersRequest(1))
|
|
ws.Push(makeWriteHeadersRequest(2))
|
|
ws.Push(makeWriteNonStreamRequest())
|
|
ws.Push(makeWriteNonStreamRequest())
|
|
ws.Push(makeWriteRSTStream(1))
|
|
|
|
// Pop all frames. Should get the non-stream and RST stream requests first,
|
|
// followed by the stream requests in any order.
|
|
var order []FrameWriteRequest
|
|
for {
|
|
wr, ok := ws.Pop()
|
|
if !ok {
|
|
break
|
|
}
|
|
order = append(order, wr)
|
|
}
|
|
t.Logf("got frames: %v", order)
|
|
if len(order) != 7 {
|
|
t.Fatalf("got %d frames, expected 6", len(order))
|
|
}
|
|
if order[0].StreamID() != 0 || order[1].StreamID() != 0 {
|
|
t.Fatal("expected non-stream frames first", order[0], order[1])
|
|
}
|
|
if _, ok := order[2].write.(StreamError); !ok {
|
|
t.Fatal("expected RST stream frames first", order[2])
|
|
}
|
|
got := make(map[uint32]bool)
|
|
for _, wr := range order[2:] {
|
|
got[wr.StreamID()] = true
|
|
}
|
|
for id := uint32(1); id <= 4; id++ {
|
|
if !got[id] {
|
|
t.Errorf("frame not found for stream %d", id)
|
|
}
|
|
}
|
|
|
|
// Verify that we clean up maps for empty queues in all cases (golang.org/issue/33812)
|
|
const arbitraryStreamID = 123
|
|
ws.Push(makeHandlerPanicRST(arbitraryStreamID))
|
|
rws := ws.(*randomWriteScheduler)
|
|
if got, want := len(rws.sq), 1; got != want {
|
|
t.Fatalf("len of 123 stream = %v; want %v", got, want)
|
|
}
|
|
_, ok := ws.Pop()
|
|
if !ok {
|
|
t.Fatal("expected to be able to Pop")
|
|
}
|
|
if got, want := len(rws.sq), 0; got != want {
|
|
t.Fatalf("len of 123 stream = %v; want %v", got, want)
|
|
}
|
|
|
|
}
|