Skip to content

Commit 6317fb4

Browse files
lfolgergopherbot
authored andcommitted
Revert "testing: simplify concurrency and cleanup logic"
reverts CL 506755 Reason for revert: This leads to deadlocks of tests in Google internal testing For #64402 Change-Id: I78329fc9dcc2377e7e880b264ac1d18d577ef99a Reviewed-on: https://go-review.googlesource.com/c/go/+/544895 Auto-Submit: Bryan Mills <[email protected]> Auto-Submit: Lasse Folger <[email protected]> Reviewed-by: Bryan Mills <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Bryan Mills <[email protected]>
1 parent d961b12 commit 6317fb4

File tree

6 files changed

+494
-431
lines changed

6 files changed

+494
-431
lines changed

src/cmd/cgo/internal/test/callback_windows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ USHORT backtrace(ULONG FramesToCapture, PVOID *BackTrace) {
2929
}
3030
3131
ControlPc = context.Rip;
32-
// Check if we left the user range.
32+
// Check if we left the user range.
3333
if (ControlPc < 0x10000) {
3434
break;
3535
}
@@ -89,7 +89,7 @@ func testCallbackCallersSEH(t *testing.T) {
8989
"test.testCallbackCallersSEH",
9090
"test.TestCallbackCallersSEH",
9191
"testing.tRunner",
92-
"testing.(*T).Run.gowrap3",
92+
"testing.(*T).Run.gowrap1",
9393
"runtime.goexit",
9494
}
9595
pc := make([]uintptr, 100)

src/testing/benchmark.go

Lines changed: 37 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,6 @@ func (b *B) ReportAllocs() {
176176

177177
// runN runs a single benchmark for the specified number of iterations.
178178
func (b *B) runN(n int) {
179-
if b.done {
180-
panic("testing: internal error: runN when benchmark is already done")
181-
}
182-
183179
benchmarkLock.Lock()
184180
defer benchmarkLock.Unlock()
185181
defer func() {
@@ -200,46 +196,46 @@ func (b *B) runN(n int) {
200196
b.previousDuration = b.duration
201197
}
202198

203-
// run1 runs the first iteration of benchFunc.
204-
//
205-
// If no more iterations of this benchmark should be done, run1 sets b.done.
206-
func (b *B) run1() {
199+
// run1 runs the first iteration of benchFunc. It reports whether more
200+
// iterations of this benchmarks should be run.
201+
func (b *B) run1() bool {
207202
if ctx := b.context; ctx != nil {
208203
// Extend maxLen, if needed.
209204
if n := len(b.name) + ctx.extLen + 1; n > ctx.maxLen {
210205
ctx.maxLen = n + 8 // Add additional slack to avoid too many jumps in size.
211206
}
212207
}
213-
214-
runOneDone := make(chan struct{})
215208
go func() {
216209
// Signal that we're done whether we return normally
217210
// or by FailNow's runtime.Goexit.
218-
defer close(runOneDone)
211+
defer func() {
212+
b.signal <- true
213+
}()
214+
219215
b.runN(1)
220216
}()
221-
<-runOneDone
222-
217+
<-b.signal
223218
if b.failed {
224219
fmt.Fprintf(b.w, "%s--- FAIL: %s\n%s", b.chatty.prefix(), b.name, b.output)
225-
b.done = true
226-
close(b.doneOrParallel)
227-
return
220+
return false
228221
}
229222
// Only print the output if we know we are not going to proceed.
230223
// Otherwise it is printed in processBench.
231-
if b.hasSub.Load() || b.skipped {
224+
b.mu.RLock()
225+
finished := b.finished
226+
b.mu.RUnlock()
227+
if b.hasSub.Load() || finished {
232228
tag := "BENCH"
233229
if b.skipped {
234230
tag = "SKIP"
235231
}
236-
if b.chatty != nil && (len(b.output) > 0 || b.skipped) {
232+
if b.chatty != nil && (len(b.output) > 0 || finished) {
237233
b.trimOutput()
238234
fmt.Fprintf(b.w, "%s--- %s: %s\n%s", b.chatty.prefix(), tag, b.name, b.output)
239235
}
240-
b.done = true
241-
close(b.doneOrParallel)
236+
return false
242237
}
238+
return true
243239
}
244240

245241
var labelsOnce sync.Once
@@ -266,10 +262,9 @@ func (b *B) run() {
266262
}
267263
}
268264

269-
// doBench calls b.launch in a separate goroutine and waits for it to complete.
270265
func (b *B) doBench() BenchmarkResult {
271266
go b.launch()
272-
<-b.doneOrParallel
267+
<-b.signal
273268
return b.result
274269
}
275270

@@ -281,10 +276,7 @@ func (b *B) launch() {
281276
// Signal that we're done whether we return normally
282277
// or by FailNow's runtime.Goexit.
283278
defer func() {
284-
b.result = BenchmarkResult{b.N, b.duration, b.bytes, b.netAllocs, b.netBytes, b.extra}
285-
b.setRanLeaf()
286-
b.done = true
287-
close(b.doneOrParallel)
279+
b.signal <- true
288280
}()
289281

290282
// Run the benchmark for at least the specified amount of time.
@@ -324,6 +316,7 @@ func (b *B) launch() {
324316
b.runN(int(n))
325317
}
326318
}
319+
b.result = BenchmarkResult{b.N, b.duration, b.bytes, b.netAllocs, b.netBytes, b.extra}
327320
}
328321

329322
// Elapsed returns the measured elapsed time of the benchmark.
@@ -557,7 +550,6 @@ func runBenchmarks(importPath string, matchString func(pat, str string) (bool, e
557550
main.chatty = newChattyPrinter(main.w)
558551
}
559552
main.runN(1)
560-
main.done = true
561553
return !main.failed
562554
}
563555

@@ -576,21 +568,18 @@ func (ctx *benchContext) processBench(b *B) {
576568
if i > 0 || j > 0 {
577569
b = &B{
578570
common: common{
579-
doneOrParallel: make(chan struct{}),
580-
name: b.name,
581-
w: b.w,
582-
chatty: b.chatty,
583-
bench: true,
571+
signal: make(chan bool),
572+
name: b.name,
573+
w: b.w,
574+
chatty: b.chatty,
575+
bench: true,
584576
},
585577
benchFunc: b.benchFunc,
586578
benchTime: b.benchTime,
587579
}
588580
b.run1()
589581
}
590-
var r BenchmarkResult
591-
if !b.done {
592-
r = b.doBench()
593-
}
582+
r := b.doBench()
594583
if b.failed {
595584
// The output could be very long here, but probably isn't.
596585
// We print it all, regardless, because we don't want to trim the reason
@@ -633,13 +622,6 @@ var hideStdoutForTesting = false
633622
// A subbenchmark is like any other benchmark. A benchmark that calls Run at
634623
// least once will not be measured itself and will be called once with N=1.
635624
func (b *B) Run(name string, f func(b *B)) bool {
636-
if b.previousN > 0 {
637-
// If the benchmark calls Run we will only call it once with N=1.
638-
// If it doesn't call Run the first time we try it, it must not
639-
// call run on subsequent invocations either.
640-
panic("testing: unexpected call to B.Run during iteration")
641-
}
642-
643625
// Since b has subbenchmarks, we will no longer run it as a benchmark itself.
644626
// Release the lock and acquire it on exit to ensure locks stay paired.
645627
b.hasSub.Store(true)
@@ -657,14 +639,14 @@ func (b *B) Run(name string, f func(b *B)) bool {
657639
n := runtime.Callers(2, pc[:])
658640
sub := &B{
659641
common: common{
660-
doneOrParallel: make(chan struct{}),
661-
name: benchName,
662-
parent: &b.common,
663-
level: b.level + 1,
664-
creator: pc[:n],
665-
w: b.w,
666-
chatty: b.chatty,
667-
bench: true,
642+
signal: make(chan bool),
643+
name: benchName,
644+
parent: &b.common,
645+
level: b.level + 1,
646+
creator: pc[:n],
647+
w: b.w,
648+
chatty: b.chatty,
649+
bench: true,
668650
},
669651
importPath: b.importPath,
670652
benchFunc: f,
@@ -697,8 +679,7 @@ func (b *B) Run(name string, f func(b *B)) bool {
697679
}
698680
}
699681

700-
sub.run1()
701-
if !sub.done {
682+
if sub.run1() {
702683
sub.run()
703684
}
704685
b.add(sub.result)
@@ -842,14 +823,13 @@ func (b *B) SetParallelism(p int) {
842823
func Benchmark(f func(b *B)) BenchmarkResult {
843824
b := &B{
844825
common: common{
845-
doneOrParallel: make(chan struct{}),
846-
w: discard{},
826+
signal: make(chan bool),
827+
w: discard{},
847828
},
848829
benchFunc: f,
849830
benchTime: benchTime,
850831
}
851-
b.run1()
852-
if !b.done {
832+
if b.run1() {
853833
b.run()
854834
}
855835
return b.result

0 commit comments

Comments
 (0)