http2: fix race condition when disabling goroutine debugging for one test

Fixes golang/go#66519

Change-Id: I7aecf20db44caaaf49754d62db193b8c42f3c63a
Reviewed-on: https://go-review.googlesource.com/c/net/+/701836
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
Damien Neil
2025-09-08 15:59:32 -07:00
committed by Gopher Robot
parent 87410502ff
commit 3b23d576ea
2 changed files with 18 additions and 6 deletions

View File

@@ -15,21 +15,32 @@ import (
"runtime"
"strconv"
"sync"
"sync/atomic"
)
var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
// Setting DebugGoroutines to false during a test to disable goroutine debugging
// results in race detector complaints when a test leaves goroutines running before
// returning. Tests shouldn't do this, of course, but when they do it generally shows
// up as infrequent, hard-to-debug flakes. (See #66519.)
//
// Disable goroutine debugging during individual tests with an atomic bool.
// (Note that it's safe to enable/disable debugging mid-test, so the actual race condition
// here is harmless.)
var disableDebugGoroutines atomic.Bool
type goroutineLock uint64
func newGoroutineLock() goroutineLock {
if !DebugGoroutines {
if !DebugGoroutines || disableDebugGoroutines.Load() {
return 0
}
return goroutineLock(curGoroutineID())
}
func (g goroutineLock) check() {
if !DebugGoroutines {
if !DebugGoroutines || disableDebugGoroutines.Load() {
return
}
if curGoroutineID() != uint64(g) {
@@ -38,7 +49,7 @@ func (g goroutineLock) check() {
}
func (g goroutineLock) checkNotOn() {
if !DebugGoroutines {
if !DebugGoroutines || disableDebugGoroutines.Load() {
return
}
if curGoroutineID() == uint64(g) {

View File

@@ -3520,9 +3520,10 @@ func testServerContentLengthCanBeDisabled(t testing.TB) {
}
func disableGoroutineTracking(t testing.TB) {
old := DebugGoroutines
DebugGoroutines = false
t.Cleanup(func() { DebugGoroutines = old })
disableDebugGoroutines.Store(true)
t.Cleanup(func() {
disableDebugGoroutines.Store(false)
})
}
func BenchmarkServer_GetRequest(b *testing.B) {