From 1dde8ef026ef3a392c03ca7e3490ad81b1ac4ddf Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Tue, 4 Apr 2023 19:25:18 +0200 Subject: [PATCH] test/integration/framework: avoid race around grpclog.SetLoggerV2 grpclog.SetLoggerV is not thread-safe and may only be called before code starts using GRPC. Calling RunCustomEtcd multiple times, for example in k8s.io/kubernetes/test/integration/apiserver.TestWatchCacheUpdatedByEtcd, causes a data race: WARNING: DATA RACE Read at 0x00000c8e8d20 by goroutine 135612: k8s.io/kubernetes/vendor/google.golang.org/grpc/grpclog.V() /home/prow/go/src/k8s.io/kubernetes/_output/local/go/src/k8s.io/kubernetes/vendor/google.golang.org/grpc/grpclog/grpclog.go:41 +0x30 k8s.io/kubernetes/vendor/google.golang.org/grpc/grpclog.(*componentData).V() /home/prow/go/src/k8s.io/kubernetes/_output/local/go/src/k8s.io/kubernetes/vendor/google.golang.org/grpc/grpclog/component.go:103 +0x4e k8s.io/kubernetes/vendor/google.golang.org/grpc/internal/transport.(*loopyWriter).run.func1() /home/prow/go/src/k8s.io/kubernetes/_output/local/go/src/k8s.io/kubernetes/vendor/google.golang.org/grpc/internal/transport/controlbuf.go:528 +0xf1 runtime.deferreturn() /home/prow/go/src/k8s.io/kubernetes/_output/local/.gimme/versions/go1.20.2.linux.amd64/src/runtime/panic.go:476 +0x32 k8s.io/kubernetes/vendor/google.golang.org/grpc/internal/transport.newHTTP2Client.func6() /home/prow/go/src/k8s.io/kubernetes/_output/local/go/src/k8s.io/kubernetes/vendor/google.golang.org/grpc/internal/transport/http2_client.go:442 +0x112 Previous write at 0x00000c8e8d20 by goroutine 140228: k8s.io/kubernetes/vendor/google.golang.org/grpc/grpclog.SetLoggerV2() /home/prow/go/src/k8s.io/kubernetes/_output/local/go/src/k8s.io/kubernetes/vendor/google.golang.org/grpc/grpclog/loggerv2.go:76 +0xc6a k8s.io/kubernetes/test/integration/framework.RunCustomEtcd() /home/prow/go/src/k8s.io/kubernetes/_output/local/go/src/k8s.io/kubernetes/test/integration/framework/etcd.go:153 +0xb89 k8s.io/kubernetes/test/integration/apiserver.multiEtcdSetup() /home/prow/go/src/k8s.io/kubernetes/_output/local/go/src/k8s.io/kubernetes/test/integration/apiserver/watchcache_test.go:40 +0xac k8s.io/kubernetes/test/integration/apiserver.TestWatchCacheUpdatedByEtcd() /home/prow/go/src/k8s.io/kubernetes/_output/local/go/src/k8s.io/kubernetes/test/integration/apiserver/watchcache_test.go:88 +0x4a testing.tRunner() /home/prow/go/src/k8s.io/kubernetes/_output/local/.gimme/versions/go1.20.2.linux.amd64/src/testing/testing.go:1576 +0x216 testing.(*T).Run.func1() /home/prow/go/src/k8s.io/kubernetes/_output/local/.gimme/versions/go1.20.2.linux.amd64/src/testing/testing.go:1629 +0x47 --- test/integration/framework/etcd.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/integration/framework/etcd.go b/test/integration/framework/etcd.go index a7a502da4ca..25e2fbbfe11 100644 --- a/test/integration/framework/etcd.go +++ b/test/integration/framework/etcd.go @@ -25,6 +25,7 @@ import ( "os" "os/exec" "strings" + "sync" "syscall" "testing" "time" @@ -83,6 +84,8 @@ func startEtcd(output io.Writer) (func(), error) { return stop, nil } +var initGRPCOnce sync.Once + // RunCustomEtcd starts a custom etcd instance for test purposes. func RunCustomEtcd(dataDir string, customFlags []string, output io.Writer) (url string, stopFn func(), err error) { // TODO: Check for valid etcd version. @@ -150,7 +153,9 @@ func RunCustomEtcd(dataDir string, customFlags []string, output io.Writer) (url // Quiet etcd logs for integration tests // Comment out to get verbose logs if desired - grpclog.SetLoggerV2(grpclog.NewLoggerV2(io.Discard, io.Discard, os.Stderr)) + initGRPCOnce.Do(func() { + grpclog.SetLoggerV2(grpclog.NewLoggerV2(io.Discard, io.Discard, os.Stderr)) + }) if err := cmd.Start(); err != nil { return "", nil, fmt.Errorf("failed to run etcd: %v", err)