Data race in DeprecationTracker when invoked from multiple goroutines
We recently bumped ginkgo from 1.16.4 to 1.16.5 in grootfs. We run our integration tests with the -race flag, and noticed the following race after the bump:
==================
WARNING: DATA RACE
Read at 0x00c0000fee08 by goroutine 75:
github.com/onsi/ginkgo/types.(*DeprecationTracker).TrackDeprecation()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/types/deprecation_support.go:99 +0x1a4
github.com/onsi/ginkgo.GinkgoParallelNode()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go:78 +0x1e4
code.cloudfoundry.org/grootfs/integration_test.glob..func3.2.1()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/integration/create_concurrency_test.go:53 +0x157
code.cloudfoundry.org/grootfs/integration_test.glob..func3.2·dwrap·3()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/integration/create_concurrency_test.go:62 +0x47
Previous write at 0x00c0000fee08 by goroutine 70:
github.com/onsi/ginkgo/types.(*DeprecationTracker).TrackDeprecation()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/types/deprecation_support.go:99 +0x2f0
github.com/onsi/ginkgo.GinkgoParallelNode()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go:78 +0x1e4
code.cloudfoundry.org/grootfs/integration_test.glob..func3.2.1()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/integration/create_concurrency_test.go:53 +0x157
code.cloudfoundry.org/grootfs/integration_test.glob..func3.2·dwrap·3()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/integration/create_concurrency_test.go:62 +0x47
Goroutine 75 (running) created at:
code.cloudfoundry.org/grootfs/integration_test.glob..func3.2()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/integration/create_concurrency_test.go:48 +0x48
github.com/onsi/ginkgo/internal/leafnodes.(*runner).runSync()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/leafnodes/runner.go:113 +0x10c
github.com/onsi/ginkgo/internal/leafnodes.(*runner).run()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/leafnodes/runner.go:64 +0x157
github.com/onsi/ginkgo/internal/leafnodes.(*ItNode).Run()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/leafnodes/it_node.go:26 +0x94
github.com/onsi/ginkgo/internal/spec.(*Spec).runSample()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/spec/spec.go:215 +0x359
github.com/onsi/ginkgo/internal/spec.(*Spec).Run()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/spec/spec.go:138 +0x1b0
github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).runSpec()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:200 +0x156
github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).runSpecs()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:170 +0x255
github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).Run()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:66 +0x138
github.com/onsi/ginkgo/internal/suite.(*Suite).Run()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/suite/suite.go:79 +0x6f5
github.com/onsi/ginkgo.runSpecsWithCustomReporters()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go:245 +0x217
github.com/onsi/ginkgo.RunSpecs()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go:220 +0x267
code.cloudfoundry.org/grootfs/integration_test.TestGroot()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/integration/groot_suite_test.go:123 +0x164
testing.tRunner()
/usr/local/go/src/testing/testing.go:1259 +0x22f
testing.(*T).Run·dwrap·21()
/usr/local/go/src/testing/testing.go:1306 +0x47
Goroutine 70 (running) created at:
code.cloudfoundry.org/grootfs/integration_test.glob..func3.2()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/integration/create_concurrency_test.go:48 +0x48
github.com/onsi/ginkgo/internal/leafnodes.(*runner).runSync()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/leafnodes/runner.go:113 +0x10c
github.com/onsi/ginkgo/internal/leafnodes.(*runner).run()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/leafnodes/runner.go:64 +0x157
github.com/onsi/ginkgo/internal/leafnodes.(*ItNode).Run()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/leafnodes/it_node.go:26 +0x94
github.com/onsi/ginkgo/internal/spec.(*Spec).runSample()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/spec/spec.go:215 +0x359
github.com/onsi/ginkgo/internal/spec.(*Spec).Run()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/spec/spec.go:138 +0x1b0
github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).runSpec()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:200 +0x156
github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).runSpecs()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:170 +0x255
github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).Run()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:66 +0x138
github.com/onsi/ginkgo/internal/suite.(*Suite).Run()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/internal/suite/suite.go:79 +0x6f5
github.com/onsi/ginkgo.runSpecsWithCustomReporters()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go:245 +0x217
github.com/onsi/ginkgo.RunSpecs()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go:220 +0x267
code.cloudfoundry.org/grootfs/integration_test.TestGroot()
/tmp/build/02610c9b/gr-release-develop/src/grootfs/integration/groot_suite_test.go:123 +0x164
testing.tRunner()
/usr/local/go/src/testing/testing.go:1259 +0x22f
testing.(*T).Run·dwrap·21()
/usr/local/go/src/testing/testing.go:1306 +0x47
==================
In our code, we call GinkgoParallelNode() from multiple goroutines. Prior to the deprecation, GinkgoParallelNode performed a simple read of a config value and returned it. Now that it is integrated with the DeprecationTracker, we see the race.
I believe this is because the TrackDeprecation func now invoked from GinkgoParallelNode performs writes to a map. This can lead to multiple goroutines writing to the same variable, which is how the Go team defines a data race:
A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write
As a temporary workaround, we have added ACK_GINKGO_DEPRECATIONS: "1.16.5" to our pipeline so that we don't reach the code with the data race.
hey there - thanks for sharing this. The 1.x line is no longer being supported and given there's a workaround I'm inclined to lave it as is and encourage folks to invest effort upgrading to 2.x instead.