fix: bump goleak past the elided-frames stack-parse panic (#660)

* fix: bump goleak past the elided-frames stack-parse panic

goleak v1.3.0's stack parser treats a "...N frames elided..." line as
a function name and panics when it can't parse one. Go elides frames
on deep/recursive stacks, which is rare but load-dependent, so this
surfaced as an intermittent panic inside goleak itself (not a real
leak) during TestDrainVolume_DispatchedGoroutineDoesNotLeak under a
full parallel preflight run. Upstream fixed this in goleak@b62053b,
unreleased as a tagged version, so this pins to the latest commit.

* test: guard goleak against panicking on elided-frame stacks

* style: trim goleak regression test comments to the 3-line max
This commit is contained in:
Josh Siviour
2026-08-03 00:49:50 +10:00
committed by GitHub
parent 3e1f9b1198
commit 972f5837ea
3 changed files with 44 additions and 2 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ require (
go.opentelemetry.io/otel/sdk/log v0.20.0
go.opentelemetry.io/otel/sdk/metric v1.44.0
go.opentelemetry.io/otel/trace v1.44.0
go.uber.org/goleak v1.3.0
go.uber.org/goleak v1.3.1-0.20260602155401-5f791e3ef83b
go.yaml.in/yaml/v3 v3.0.4
golang.org/x/crypto v0.54.0
golang.org/x/sync v0.22.0
+2 -1
View File
@@ -1805,8 +1805,9 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/goleak v1.3.1-0.20260602155401-5f791e3ef83b h1:FHYZT12VzXnb6P399kd1i9Ai7aLF+CFSUsOFylDt7Lk=
go.uber.org/goleak v1.3.1-0.20260602155401-5f791e3ef83b/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+41
View File
@@ -154,3 +154,44 @@ func assertStuckMarkedFailed(t *testing.T, m *Manager, rt *recordedTransitions,
assert.Contains(t, targets, StateTerminated,
"terminal transition must land in Terminated")
}
// deepRecurse recurses past the 100 frames runtime.Stack keeps before it
// collapses the rest into a literal "...N frames elided..." line. Kept
// non-inlinable so the recursion reaches the goroutine's stack trace.
//
//go:noinline
func deepRecurse(n int, ready chan<- struct{}, block <-chan struct{}) int {
if n <= 0 {
close(ready)
<-block
return 0
}
return deepRecurse(n-1, ready, block) + n
}
// TestGoleakParsesElidedFrameStacks guards against goleak's stack parser
// panicking on the "...N frames elided..." line runtime.Stack emits for
// goroutines parked past 100 frames deep. v1.3.0 reads it as a function name.
func TestGoleakParsesElidedFrameStacks(t *testing.T) {
ready := make(chan struct{})
block := make(chan struct{})
done := make(chan struct{})
// 200 frames guarantees the elided-frames line regardless of the
// runtime's exact truncation threshold, while the goroutine stays
// parked on <-block so its stack is captured mid-recursion.
go func() {
defer close(done)
deepRecurse(200, ready, block)
}()
<-ready
assert.NotPanics(t, func() {
// Find legitimately reports the parked goroutine as a leak;
// only a panic escaping the call is a failure here.
_ = goleak.Find()
})
close(block)
<-done
}