benbjohnson / clock

Clock is a small library for mocking time in Go.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Re-entrant mock timer calls cause deadlock

evanj opened this issue · comments

I know this repository is no longer maintained, but I just want to record this somewhere for future people who might run into this.

Timers created with AfterFunc() which call back into the timer code by calling Timer.Close() can cause a deadlock. This is because Timer.Tick() calls the function while holding the mock time source's lock. Example test that reproduces the problem:

func TestClockReentrantDeadlock(t *testing.T) {
    mockedClock := clock.NewMock()
    timer20 := mockedClock.Timer(20 * time.Second)
    go func() {
            v := <-timer20.C
            panic(fmt.Sprintf("timer should not have ticked: %v", v))
    }()
    mockedClock.AfterFunc(10*time.Second, func() {
            timer20.Stop()
    })

    mockedClock.Add(15 * time.Second)
    mockedClock.Add(15 * time.Second)
}