From a76144192663cf35123f030e5ec37532e250bbbd Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Mon, 18 May 2026 14:16:22 -0700 Subject: [PATCH] fix(test): reserve mini ports on all interfaces; bound risingwave cleanup shell (#9545) The 127.0.0.1-only reservation in AllocateMiniPorts/AllocatePortSet let another process hold the gRPC port on a different interface, so weed mini's isPortAvailable check failed and it shifted master.grpc. weed shell -master= still derives grpc as HTTP+10000 and dialed the unused port, hanging until the 30s context deadline killed it. Bind the reservation listeners on :port to match mini's check. Also bound listFilerContents in catalog_risingwave with a 30s exec.CommandContext so a hung weed shell during failure-cleanup can't burn the 20-minute test budget. --- test/s3tables/catalog_risingwave/setup_test.go | 7 ++++++- test/testutil/ports.go | 17 ++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/test/s3tables/catalog_risingwave/setup_test.go b/test/s3tables/catalog_risingwave/setup_test.go index 527a28999..b893c1d91 100644 --- a/test/s3tables/catalog_risingwave/setup_test.go +++ b/test/s3tables/catalog_risingwave/setup_test.go @@ -411,7 +411,12 @@ func createIcebergTable(t *testing.T, env *TestEnvironment, bucketName, namespac func listFilerContents(t *testing.T, env *TestEnvironment, path string) { t.Helper() - cmd := exec.Command("weed", "shell", + // Bound diagnostic listing so a hung weed shell during cleanup can't + // burn the whole 20-minute test timeout. + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + cmd := exec.CommandContext(ctx, "weed", "shell", fmt.Sprintf("-master=%s", env.hostMasterAddress()), ) cmd.Stdin = strings.NewReader(fmt.Sprintf("fs.ls -R %s\nexit\n", path)) diff --git a/test/testutil/ports.go b/test/testutil/ports.go index 687d98862..f5dc888dc 100644 --- a/test/testutil/ports.go +++ b/test/testutil/ports.go @@ -51,6 +51,13 @@ func MustAllocatePorts(t *testing.T, count int) []int { // from recycling ports between allocations. Use this when ports will be // passed to weed mini without explicit gRPC port flags, so mini will // derive gRPC ports as HTTP + 10000. +// +// Listeners are bound on all interfaces (":port") rather than 127.0.0.1 +// to match weed mini's availability check (isPortAvailable). A port can +// be free on loopback but held by another process on a different +// interface; reserving only on loopback lets mini's check fail and +// trigger gRPC port shifting, which then causes weed shell to dial the +// wrong port and hang. func AllocateMiniPorts(count int) ([]int, error) { const ( minPort = 10000 @@ -75,12 +82,12 @@ func AllocateMiniPorts(count int) ([]int, error) { continue } - l1, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port)) + l1, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) if err != nil { continue } - l2, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", grpcPort)) + l2, err := net.Listen("tcp", fmt.Sprintf(":%d", grpcPort)) if err != nil { l1.Close() continue @@ -145,11 +152,11 @@ func AllocatePortSet(miniCount, regularCount int) (mini []int, regular []int, er if reserved[port] || reserved[grpcPort] { continue } - l1, lErr := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port)) + l1, lErr := net.Listen("tcp", fmt.Sprintf(":%d", port)) if lErr != nil { continue } - l2, lErr := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", grpcPort)) + l2, lErr := net.Listen("tcp", fmt.Sprintf(":%d", grpcPort)) if lErr != nil { l1.Close() continue @@ -168,7 +175,7 @@ func AllocatePortSet(miniCount, regularCount int) (mini []int, regular []int, er regular = make([]int, 0, regularCount) for i := 0; i < regularCount; i++ { - l, lErr := net.Listen("tcp", "127.0.0.1:0") + l, lErr := net.Listen("tcp", ":0") if lErr != nil { return nil, nil, lErr }