From 31f1a6ccc386b2c590849a869237634217b9ef6f Mon Sep 17 00:00:00 2001 From: Jake Alti Date: Wed, 20 May 2026 16:03:04 -0700 Subject: [PATCH 1/3] kube: handle goaway test fixture conns concurrently --- lib/kube/proxy/forwarder_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/kube/proxy/forwarder_test.go b/lib/kube/proxy/forwarder_test.go index d0773ef697dc0..af262220bf851 100644 --- a/lib/kube/proxy/forwarder_test.go +++ b/lib/kube/proxy/forwarder_test.go @@ -2074,9 +2074,7 @@ func (g *goawayServer) Serve() error { return err } - if err := g.handleConn(conn); err != nil { - return err - } + go func() { _ = g.handleConn(conn) }() } } From dd75c85ca5e9b6a59822a2dd1159e84acd29c4f1 Mon Sep 17 00:00:00 2001 From: Jake Alti Date: Thu, 21 May 2026 14:16:55 -0700 Subject: [PATCH 2/3] kube: wait for goaway handler goroutines on close --- lib/kube/proxy/forwarder_test.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/kube/proxy/forwarder_test.go b/lib/kube/proxy/forwarder_test.go index af262220bf851..41707512b9bb8 100644 --- a/lib/kube/proxy/forwarder_test.go +++ b/lib/kube/proxy/forwarder_test.go @@ -2053,6 +2053,10 @@ func TestGOAWAYHandling_Concurrent(t *testing.T) { type goawayServer struct { listener net.Listener tlsConfig *tls.Config + + mu sync.Mutex + conns []net.Conn + wg sync.WaitGroup } // URL returns the address clients should use to connect to the server. @@ -2074,13 +2078,25 @@ func (g *goawayServer) Serve() error { return err } - go func() { _ = g.handleConn(conn) }() + g.mu.Lock() + g.conns = append(g.conns, conn) + g.wg.Go(func() { _ = g.handleConn(conn) }) + g.mu.Unlock() } } -// Close terminates the server and unblocks any calls to [Serve]. +// Close terminates the server and unblocks any calls to [Serve], then +// closes all in-flight connections and waits for their handler goroutines +// to exit. func (g *goawayServer) Close() error { - return g.listener.Close() + err := g.listener.Close() + g.mu.Lock() + for _, c := range g.conns { + _ = c.Close() + } + g.mu.Unlock() + g.wg.Wait() + return err } // handleConn performs the initial HTTP/2 message exchange and then From dde7a809eff895e23ed749c26cfb0a88fd38f526 Mon Sep 17 00:00:00 2001 From: Jake Alti Date: Thu, 21 May 2026 14:32:19 -0700 Subject: [PATCH 3/3] kube: drop late-arriving goaway conns after close --- lib/kube/proxy/forwarder_test.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/kube/proxy/forwarder_test.go b/lib/kube/proxy/forwarder_test.go index 41707512b9bb8..e07f07b84a8eb 100644 --- a/lib/kube/proxy/forwarder_test.go +++ b/lib/kube/proxy/forwarder_test.go @@ -2054,9 +2054,10 @@ type goawayServer struct { listener net.Listener tlsConfig *tls.Config - mu sync.Mutex - conns []net.Conn - wg sync.WaitGroup + mu sync.Mutex + closed bool + conns []net.Conn + wg sync.WaitGroup } // URL returns the address clients should use to connect to the server. @@ -2079,6 +2080,11 @@ func (g *goawayServer) Serve() error { } g.mu.Lock() + if g.closed { + g.mu.Unlock() + _ = conn.Close() + continue + } g.conns = append(g.conns, conn) g.wg.Go(func() { _ = g.handleConn(conn) }) g.mu.Unlock() @@ -2091,6 +2097,7 @@ func (g *goawayServer) Serve() error { func (g *goawayServer) Close() error { err := g.listener.Close() g.mu.Lock() + g.closed = true for _, c := range g.conns { _ = c.Close() }