Skip to content

Commit da68477

Browse files
authored
fix(leak): init() check for goroutine profile might fail under pressure: now wait a bit (#73)
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
1 parent 2d5a554 commit da68477

File tree

2 files changed

+26
-10
lines changed

2 files changed

+26
-10
lines changed

.github/wordlist.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,6 @@ UUID
9999
Unmarshalers
100100
XYZ
101101
YAML
102-
- "dependending" - should be "depending"
103-
- "logics" - should be "logic" (uncountable noun)
104-
- "maintainance" - should be "maintenance"
105102
ad'hoc
106103
agentic
107104
allocs

internal/leak/leak.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ import (
1919

2020
const labelKey = "testify-leak-check"
2121

22+
const (
23+
maxAttempts = 20
24+
maxWait = 100 * time.Millisecond
25+
waitFactor = 2
26+
)
27+
2228
func init() { //nolint:gochecknoinits // this init check is justify by the use of an internal volatile API.
2329
// check that the profile API behaves as expected or panic.
2430
//
@@ -42,6 +48,24 @@ func init() { //nolint:gochecknoinits // this init check is justify by the use o
4248
needle := buildNeedle(id)
4349
profile := captureProfile()
4450
match := extractLabeledBlocks(profile, needle)
51+
if match == "" {
52+
// goroutine may not be scheduled yet: wait a bit before taking a decision
53+
54+
wait := time.Microsecond
55+
for range maxAttempts {
56+
time.Sleep(wait) // brief retry: goroutines may be mid-exit.
57+
profile = captureProfile()
58+
match = extractLabeledBlocks(profile, needle)
59+
if match != "" {
60+
break
61+
}
62+
63+
// retry — goroutine might still be exiting
64+
// wait exponential backoff, capped to maxWait
65+
wait = min(wait*waitFactor, maxWait)
66+
}
67+
}
68+
4569
close(blocker)
4670
wg.Wait()
4771
if match == "" {
@@ -69,16 +93,11 @@ func Leaked(ctx context.Context, tested func()) string {
6993
return "" // early exit: clean state
7094
}
7195

72-
const (
73-
maxAttempts = 20
74-
maxWait = 100 * time.Millisecond
75-
waitFactor = 2
76-
)
7796
wait := time.Microsecond
7897
for range maxAttempts {
7998
time.Sleep(wait) // brief retry: goroutines may be mid-exit.
80-
profile := captureProfile()
81-
match := extractLabeledBlocks(profile, needle)
99+
profile = captureProfile()
100+
match = extractLabeledBlocks(profile, needle)
82101
if match == "" {
83102
return "" // clean
84103
}

0 commit comments

Comments
 (0)