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

Commit

Permalink
Merge pull request #22 from danielnelson/fix-data-race
Browse files Browse the repository at this point in the history
Fix data race between timer Reset and Add; unlock before gosched
  • Loading branch information
benbjohnson authored May 18, 2020
2 parents dcb3cf9 + 8d5f46b commit e68937b
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
5 changes: 2 additions & 3 deletions clock.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,8 @@ func (t *Timer) Reset(d time.Duration) bool {
return t.timer.Reset(d)
}

t.next = t.mock.now.Add(d)
t.mock.mu.Lock()
t.next = t.mock.now.Add(d)
defer t.mock.mu.Unlock()

registered := !t.stopped
Expand All @@ -296,9 +296,8 @@ func (t *internalTimer) Tick(now time.Time) {
}
t.mock.removeClockTimer((*internalTimer)(t))
t.mock.mu.Lock()
defer t.mock.mu.Unlock()

t.stopped = true
t.mock.mu.Unlock()
gosched()
}

Expand Down
24 changes: 24 additions & 0 deletions clock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,30 @@ func TestClock_Timer_Reset(t *testing.T) {
}
}

// Ensure reset can be called immediately after reading channel
func TestClock_Timer_Reset_Unlock(t *testing.T) {
clock := NewMock()
timer := clock.Timer(1 * time.Second)

var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()

select {
case <-timer.C:
timer.Reset(1 * time.Second)
}

select {
case <-timer.C:
}
}()

clock.Add(2 * time.Second)
wg.Wait()
}

// Ensure that the mock's After channel sends at the correct time.
func TestMock_After(t *testing.T) {
var ok int32
Expand Down

0 comments on commit e68937b

Please sign in to comment.