From 02a620e7a531b97005bb52830244e7b6b0a00fb0 Mon Sep 17 00:00:00 2001 From: Daniel Nelson Date: Wed, 13 May 2020 14:53:28 -0700 Subject: [PATCH 1/2] Fix data race between Reset and Add --- clock.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clock.go b/clock.go index ab7ebc5..1887795 100644 --- a/clock.go +++ b/clock.go @@ -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 From 8d5f46b7dee5e3d45d746ba14507ac80207702cc Mon Sep 17 00:00:00 2001 From: Daniel Nelson Date: Wed, 13 May 2020 15:01:57 -0700 Subject: [PATCH 2/2] Unlock mutex before running gosched --- clock.go | 3 +-- clock_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/clock.go b/clock.go index 1887795..14ee076 100644 --- a/clock.go +++ b/clock.go @@ -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() } diff --git a/clock_test.go b/clock_test.go index 70cc7c7..275f5b9 100644 --- a/clock_test.go +++ b/clock_test.go @@ -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