Skip to content

Commit 156a1cb

Browse files
committed
fix race + add test for detect race
1 parent f066f3f commit 156a1cb

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

internal/pool/pool.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,31 +66,46 @@ func (s *safeStats) Get() stats.Stats {
6666
}
6767

6868
func (s *safeStats) Index() statsItemAddr {
69+
s.mu.RLock()
70+
defer s.mu.RUnlock()
71+
6972
return statsItemAddr{
7073
v: &s.v.Index,
7174
onChange: func(f func()) {
7275
s.mu.WithLock(f)
73-
s.onChange(s.v)
76+
if s.onChange != nil {
77+
s.onChange(s.Get())
78+
}
7479
},
7580
}
7681
}
7782

7883
func (s *safeStats) Idle() statsItemAddr {
84+
s.mu.RLock()
85+
defer s.mu.RUnlock()
86+
7987
return statsItemAddr{
8088
v: &s.v.Idle,
8189
onChange: func(f func()) {
8290
s.mu.WithLock(f)
83-
s.onChange(s.v)
91+
if s.onChange != nil {
92+
s.onChange(s.Get())
93+
}
8494
},
8595
}
8696
}
8797

8898
func (s *safeStats) InUse() statsItemAddr {
99+
s.mu.RLock()
100+
defer s.mu.RUnlock()
101+
89102
return statsItemAddr{
90103
v: &s.v.InUse,
91104
onChange: func(f func()) {
92105
s.mu.WithLock(f)
93-
s.onChange(s.v)
106+
if s.onChange != nil {
107+
s.onChange(s.Get())
108+
}
94109
},
95110
}
96111
}

internal/pool/pool_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package pool
33
import (
44
"context"
55
"errors"
6+
"math/rand"
67
"sync"
78
"sync/atomic"
89
"testing"
@@ -289,3 +290,31 @@ func TestPool(t *testing.T) {
289290
}, xtest.StopAfter(42*time.Second))
290291
})
291292
}
293+
294+
func TestSafeStatsRace(t *testing.T) {
295+
xtest.TestManyTimes(t, func(t testing.TB) {
296+
var (
297+
wg sync.WaitGroup
298+
s = &safeStats{}
299+
)
300+
wg.Add(10000)
301+
for range make([]struct{}, 10000) {
302+
go func() {
303+
defer wg.Done()
304+
require.NotPanics(t, func() {
305+
switch rand.Int31n(4) { //nolint:gosec
306+
case 0:
307+
s.Index().Inc()
308+
case 1:
309+
s.InUse().Inc()
310+
case 2:
311+
s.Idle().Inc()
312+
default:
313+
s.Get()
314+
}
315+
})
316+
}()
317+
}
318+
wg.Wait()
319+
}, xtest.StopAfter(5*time.Second))
320+
}

0 commit comments

Comments
 (0)