Skip to content
This repository was archived by the owner on May 18, 2023. It is now read-only.

Commit e68937b

Browse files
authored
Merge pull request #22 from danielnelson/fix-data-race
Fix data race between timer Reset and Add; unlock before gosched
2 parents dcb3cf9 + 8d5f46b commit e68937b

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

clock.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,8 @@ func (t *Timer) Reset(d time.Duration) bool {
272272
return t.timer.Reset(d)
273273
}
274274

275-
t.next = t.mock.now.Add(d)
276275
t.mock.mu.Lock()
276+
t.next = t.mock.now.Add(d)
277277
defer t.mock.mu.Unlock()
278278

279279
registered := !t.stopped
@@ -296,9 +296,8 @@ func (t *internalTimer) Tick(now time.Time) {
296296
}
297297
t.mock.removeClockTimer((*internalTimer)(t))
298298
t.mock.mu.Lock()
299-
defer t.mock.mu.Unlock()
300-
301299
t.stopped = true
300+
t.mock.mu.Unlock()
302301
gosched()
303302
}
304303

clock_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,30 @@ func TestClock_Timer_Reset(t *testing.T) {
211211
}
212212
}
213213

214+
// Ensure reset can be called immediately after reading channel
215+
func TestClock_Timer_Reset_Unlock(t *testing.T) {
216+
clock := NewMock()
217+
timer := clock.Timer(1 * time.Second)
218+
219+
var wg sync.WaitGroup
220+
wg.Add(1)
221+
go func() {
222+
defer wg.Done()
223+
224+
select {
225+
case <-timer.C:
226+
timer.Reset(1 * time.Second)
227+
}
228+
229+
select {
230+
case <-timer.C:
231+
}
232+
}()
233+
234+
clock.Add(2 * time.Second)
235+
wg.Wait()
236+
}
237+
214238
// Ensure that the mock's After channel sends at the correct time.
215239
func TestMock_After(t *testing.T) {
216240
var ok int32

0 commit comments

Comments
 (0)