]> Cypherpunks repositories - gostls13.git/commitdiff
testing: fix deadlock with t.Parallel in testing seed corpus
authorKatie Hockman <katie@golang.org>
Wed, 22 Dec 2021 15:34:55 +0000 (10:34 -0500)
committerKatie Hockman <katie@golang.org>
Thu, 6 Jan 2022 22:12:11 +0000 (22:12 +0000)
The c.startParallel channel on the testContext is stuck
in t.Parallel() because c.running starts at 1 for the main
fuzz parent test, and is causing a deadlock because it is
never released. It would normally be released by tRunner,
but needs to instead be released by fRunner instead for fuzz
tests.

Fixes #50217

Change-Id: I2d010e9adddfd8e8321ff2f9dd2e43daf46c128f
Reviewed-on: https://go-review.googlesource.com/c/go/+/374054
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/go/testdata/script/test_fuzz_parallel.txt
src/testing/fuzz.go

index 1795e0b2a5178a5a0f4c5a20fa49b380d827ff78..e6325208d008ada1f0735ff8137fedc12ed6026d 100644 (file)
@@ -13,6 +13,13 @@ go test -run=FuzzSeed
 ! go test -run=FuzzMutate -fuzz=FuzzMutate
 exists testdata/fuzz/FuzzMutate
 
+# Testdata should now contain a corpus entry which will fail FuzzMutate.
+# Run the test without fuzzing, setting -parallel to different values to make
+# sure it fails, and doesn't hang.
+! go test -run=FuzzMutate -parallel=1
+! go test -run=FuzzMutate -parallel=2
+! go test -run=FuzzMutate -parallel=4
+
 -- go.mod --
 module fuzz_parallel
 
index efb59b3e57ad01dc2f01fd6ae535a384fcabf7d6..037d531acfcf1cd0f6300883fe03e2dc22265b7a 100644 (file)
@@ -323,10 +323,10 @@ func (f *F) Fuzz(ff any) {
                        for _, v := range e.Values {
                                args = append(args, reflect.ValueOf(v))
                        }
-                       // Before reseting the current coverage, defer the snapshot so that we
-                       // make sure it is called right before the tRunner function exits,
-                       // regardless of whether it was executed cleanly, panicked, or if the
-                       // fuzzFn called t.Fatal.
+                       // Before resetting the current coverage, defer the snapshot so that
+                       // we make sure it is called right before the tRunner function
+                       // exits, regardless of whether it was executed cleanly, panicked,
+                       // or if the fuzzFn called t.Fatal.
                        defer f.fuzzContext.deps.SnapshotCoverage()
                        f.fuzzContext.deps.ResetCoverage()
                        fn.Call(args)
@@ -666,6 +666,7 @@ func fRunner(f *F, fn func(*F)) {
                        // This only affects fuzz tests run as normal tests.
                        // While fuzzing, T.Parallel has no effect, so f.sub is empty, and this
                        // branch is not taken. f.barrier is nil in that case.
+                       f.testContext.release()
                        close(f.barrier)
                        // Wait for the subtests to complete.
                        for _, sub := range f.sub {