@@ -19,6 +19,12 @@ import (
1919
2020const labelKey = "testify-leak-check"
2121
22+ const (
23+ maxAttempts = 20
24+ maxWait = 100 * time .Millisecond
25+ waitFactor = 2
26+ )
27+
2228func 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