From bae01a7353ec2859fef5173ae4a2cfec0d5ce017 Mon Sep 17 00:00:00 2001 From: Egon Elbre Date: Thu, 8 May 2025 17:39:30 +0300 Subject: [PATCH 1/5] trace: add missing td tag Change-Id: I4f99953e028a6e397c62605f39b73872abf960bd Reviewed-on: https://go-review.googlesource.com/c/net/+/670995 Reviewed-by: Sean Liao Auto-Submit: Sean Liao Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI Reviewed-by: Michael Knyszek --- trace/events.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trace/events.go b/trace/events.go index c646a6952e..3aaffdd1f7 100644 --- a/trace/events.go +++ b/trace/events.go @@ -508,7 +508,7 @@ const eventsHTML = ` {{$el.When}} {{$el.ElapsedTime}} - {{$el.Title}} + {{$el.Title}} {{if $.Expanded}} From 919c6bc7ad594b151348609479daf6d6d388c01e Mon Sep 17 00:00:00 2001 From: Evan Jones Date: Tue, 6 May 2025 13:00:55 -0400 Subject: [PATCH 2/5] http2: use an array instead of a map in typeFrameParser FrameType is a dense integer range, so we can store the frameParsers in an array instead of a map. This should be a very small performance win on all Go http2 servers. For high QPS gRPC services, this function is visible in the Go profiler. For example, it shows up as 0.16% of all CPU time on one production service at Datadog. Change FrameType.String() to use the same pattern. Add a test for testFrameType with unknown FrameTypes. Fixes golang/go#73613 Change-Id: I5f5b523e011a99d6b428cbdbfd97415e488169d1 Reviewed-on: https://go-review.googlesource.com/c/net/+/670415 Reviewed-by: Sean Liao Reviewed-by: Cherry Mui Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI --- http2/frame.go | 14 +++++++------- http2/frame_test.go | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/http2/frame.go b/http2/frame.go index 97bd8b06f7..e6f728c261 100644 --- a/http2/frame.go +++ b/http2/frame.go @@ -39,7 +39,7 @@ const ( FrameContinuation FrameType = 0x9 ) -var frameName = map[FrameType]string{ +var frameNames = [...]string{ FrameData: "DATA", FrameHeaders: "HEADERS", FramePriority: "PRIORITY", @@ -53,10 +53,10 @@ var frameName = map[FrameType]string{ } func (t FrameType) String() string { - if s, ok := frameName[t]; ok { - return s + if int(t) < len(frameNames) { + return frameNames[t] } - return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t)) + return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", t) } // Flags is a bitmask of HTTP/2 flags. @@ -124,7 +124,7 @@ var flagName = map[FrameType]map[Flags]string{ // might be 0). type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) -var frameParsers = map[FrameType]frameParser{ +var frameParsers = [...]frameParser{ FrameData: parseDataFrame, FrameHeaders: parseHeadersFrame, FramePriority: parsePriorityFrame, @@ -138,8 +138,8 @@ var frameParsers = map[FrameType]frameParser{ } func typeFrameParser(t FrameType) frameParser { - if f := frameParsers[t]; f != nil { - return f + if int(t) < len(frameParsers) { + return frameParsers[t] } return parseUnknownFrame } diff --git a/http2/frame_test.go b/http2/frame_test.go index 86e5d4f80d..68505317e1 100644 --- a/http2/frame_test.go +++ b/http2/frame_test.go @@ -1258,3 +1258,21 @@ func TestSettingsDuplicates(t *testing.T) { } } + +func TestTypeFrameParser(t *testing.T) { + if len(frameNames) != len(frameParsers) { + t.Errorf("expected len(frameNames)=%d to equal len(frameParsers)=%d", + len(frameNames), len(frameParsers)) + } + + // typeFrameParser() for an unknown type returns a function that returns UnknownFrame + unknownFrameType := FrameType(FrameContinuation + 1) + unknownParser := typeFrameParser(unknownFrameType) + frame, err := unknownParser(nil, FrameHeader{}, nil, nil) + if err != nil { + t.Errorf("unknownParser() must not return an error: %v", err) + } + if _, isUnknown := frame.(*UnknownFrame); !isUnknown { + t.Errorf("expected UnknownFrame, got %T", frame) + } +} From ef33bc08f8e2986804d7a70cc58a40f437bf5205 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Thu, 22 May 2025 09:29:25 -0700 Subject: [PATCH 3/5] internal/http3: use bubbled context in synctest tests Avoid using T.Context within a synctest bubble. If the Context's Done channel is created outside the bubble, waiting on it within the bubble is durably blocking. If it's created within the bubble, the testing package encounters a panic when closing it after CL 671960. Instead, create our own Context within the bubble and cancel it before the bubble is destroyed. This will be entirely obviated by synctest.Test, which creates a testing.T that returns a properly bubbled context. Change-Id: Iff93c296ccbc1ece8172cb0a60e626ea1bd895ad Reviewed-on: https://go-review.googlesource.com/c/net/+/675615 LUCI-TryBot-Result: Go LUCI Auto-Submit: Damien Neil Reviewed-by: Jonathan Amsterdam --- internal/http3/http3_synctest_test.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/internal/http3/http3_synctest_test.go b/internal/http3/http3_synctest_test.go index ad26c6de09..a9c0ac2906 100644 --- a/internal/http3/http3_synctest_test.go +++ b/internal/http3/http3_synctest_test.go @@ -7,6 +7,7 @@ package http3 import ( + "context" "slices" "testing" "testing/synctest" @@ -14,9 +15,16 @@ import ( // runSynctest runs f in a synctest.Run bubble. // It arranges for t.Cleanup functions to run within the bubble. +// TODO: Replace with synctest.Test, which handles all this properly. func runSynctest(t *testing.T, f func(t testing.TB)) { synctest.Run(func() { - ct := &cleanupT{T: t} + // Create a context within the bubble, rather than using t.Context. + ctx, cancel := context.WithCancel(context.Background()) + ct := &cleanupT{ + T: t, + ctx: ctx, + cancel: cancel, + } defer ct.done() f(ct) }) @@ -33,6 +41,8 @@ func runSynctestSubtest(t *testing.T, name string, f func(t testing.TB)) { // Used to execute cleanup functions within a synctest bubble. type cleanupT struct { *testing.T + ctx context.Context + cancel context.CancelFunc cleanups []func() } @@ -41,7 +51,13 @@ func (t *cleanupT) Cleanup(f func()) { t.cleanups = append(t.cleanups, f) } +// Context replaces T.Context. +func (t *cleanupT) Context() context.Context { + return t.ctx +} + func (t *cleanupT) done() { + t.cancel() for _, f := range slices.Backward(t.cleanups) { f() } From 15f7d40345230297a2172897200715909e359dd4 Mon Sep 17 00:00:00 2001 From: Chressie Himpel Date: Mon, 26 May 2025 08:33:16 +0200 Subject: [PATCH 4/5] http2: correctly wrap ErrFrameTooLarge in Framer.ReadFrame In Framer.ReadFrame's frame-too-large check, the code that checks for HTTP/1.1 looking frames accidentally wrapped the unrelated err from the previous readFrameHeader call instead of ErrFrameTooLarge. Fix that. Change-Id: I2237759eaad8c6e06e7195c50410abb5792e57ea Reviewed-on: https://go-review.googlesource.com/c/net/+/676218 Reviewed-by: Chressie Himpel Reviewed-by: Damien Neil LUCI-TryBot-Result: Go LUCI --- http2/frame.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http2/frame.go b/http2/frame.go index e6f728c261..db3264da8c 100644 --- a/http2/frame.go +++ b/http2/frame.go @@ -509,7 +509,7 @@ func (fr *Framer) ReadFrame() (Frame, error) { } if fh.Length > fr.maxReadSize { if fh == invalidHTTP1LookingFrameHeader() { - return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", err) + return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge) } return nil, ErrFrameTooLarge } From 6e41caea7e521db69a7de02895624c195575ed63 Mon Sep 17 00:00:00 2001 From: Gopher Robot Date: Thu, 5 Jun 2025 12:05:38 -0700 Subject: [PATCH 5/5] go.mod: update golang.org/x dependencies Update golang.org/x dependencies to their latest tagged versions. Change-Id: Ief62c666e731ea5aa7bbf9b6be66c47cb463f867 Reviewed-on: https://go-review.googlesource.com/c/net/+/679315 Reviewed-by: Dmitri Shuralyov Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI Auto-Submit: Gopher Robot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index eee2e07658..92c7b8d76c 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module golang.org/x/net go 1.23.0 require ( - golang.org/x/crypto v0.38.0 + golang.org/x/crypto v0.39.0 golang.org/x/sys v0.33.0 golang.org/x/term v0.32.0 - golang.org/x/text v0.25.0 + golang.org/x/text v0.26.0 ) diff --git a/go.sum b/go.sum index f46e8c676b..6b81fa4744 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=