Called testing.Benchmark in a Benchmark. The reason for this is that I wanted to check during benchmarks which one of two possible implementations would be faster on the current machine and for a set of given inputs.
Here is a minimal repro that should be run as a benchmark to crash (must be in *_test.go and should be run with go test -bench=. )
During the first iteration of benchFuncrun1 is executed. run1 invokes runN which will run run1. The issue is that runN tries to acquire a global lock while holding it, causing the deadlock.
Source for runN:
// runN runs a single benchmark for the specified number of iterations.
func (b *B) runN(n int) {
benchmarkLock.Lock() // ← acquiring global mutex
defer benchmarkLock.Unlock()
// Try to get a comparable environment for each run
// by clearing garbage from previous runs.
runtime.GC()
b.raceErrors = -race.Errors()
b.N = n
b.parallelism = 1
b.ResetTimer()
b.StartTimer()
b.benchFunc(b) // ← This will run run1, which will call runN, which will deadlock
Source for run1:
// run1 runs the first iteration of benchFunc. It returns whether more// iterations of this benchmarks should be run.func (b*B) run1() bool {
ifctx:=b.context; ctx!=nil {
// Extend maxLen, if needed.ifn:=len(b.name) +ctx.extLen+1; n>ctx.maxLen {
ctx.maxLen=n+8// Add additional slack to avoid too many jumps in size.
}
}
gofunc() {
// Signal that we're done whether we return normally// or by FailNow's runtime.Goexit.deferfunc() {
b.signal<-true
}()
b.runN(1) // ← Running runN
}()
<-b.signal
The text was updated successfully, but these errors were encountered:
empijei
changed the title
testing: Benchmark calls in benchmarks run deadlock
testing: Benchmark calls during benchmarks deadlock
Jan 14, 2019
Are calls to testing.Benchmark within a benchmark supported? But I agree that something is wrong. Even if they're not supported, the testing package should error properly instead of deadlocking.
mvdan
added
the
NeedsFix
The path to resolution is known, but the work has not been done.
label
Jan 14, 2019
Benchmark benchmarks a single function. Useful for creating custom benchmarks that do not use the "go test" command.
Should this be corrected to something that specifies it should only be used for those cases that do not use "go test" or it is clear enough and I just misread it?
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Called testing.Benchmark in a Benchmark. The reason for this is that I wanted to check during benchmarks which one of two possible implementations would be faster on the current machine and for a set of given inputs.
Here is a minimal repro that should be run as a benchmark to crash (must be in *_test.go and should be run with
go test -bench=.
)What did you expect to see?
"Difference between executions is ~1ns
What did you see instead?
Probable cause
During the first iteration of
benchFunc
run1
is executed.run1
invokesrunN
which will runrun1
. The issue is thatrunN
tries to acquire a global lock while holding it, causing the deadlock.Source for
runN
:Source for
run1
:The text was updated successfully, but these errors were encountered: