Commit 7b76175a authored by Rob Pike's avatar Rob Pike

time.Ticker: fix bug arising when all tickers are dead.

thanks to yglgogo for analysis.

Fixes #593.

R=rsc
CC=golang-dev
https://golang.org/cl/210044
parent 3dc04f4a
...@@ -39,16 +39,23 @@ type alarmer struct { ...@@ -39,16 +39,23 @@ type alarmer struct {
// Set alarm to go off at time ns, if not already set earlier. // Set alarm to go off at time ns, if not already set earlier.
func (a *alarmer) set(ns int64) { func (a *alarmer) set(ns int64) {
// If there's no wakeLoop or the next tick we expect is too late, start a new wakeLoop switch {
if a.wakeMeAt == nil || a.wakeTime > ns { case a.wakeTime > ns:
// Stop previous wakeLoop. // Next tick we expect is too late; shut down the late runner
if a.wakeMeAt != nil { // and (after fallthrough) start a new wakeLoop.
a.wakeMeAt <- -1 a.wakeMeAt <- -1
} fallthrough
case a.wakeMeAt == nil:
// There's no wakeLoop, start one.
a.wakeMeAt = make(chan int64, 10) a.wakeMeAt = make(chan int64, 10)
go wakeLoop(a.wakeMeAt, a.wakeUp) go wakeLoop(a.wakeMeAt, a.wakeUp)
fallthrough
case a.wakeTime == 0:
// Nobody else is waiting; it's just us.
a.wakeTime = ns a.wakeTime = ns
a.wakeMeAt <- ns a.wakeMeAt <- ns
default:
// There's already someone scheduled.
} }
} }
...@@ -141,6 +148,8 @@ func tickerLoop() { ...@@ -141,6 +148,8 @@ func tickerLoop() {
// Please send wakeup at earliest required time. // Please send wakeup at earliest required time.
// If there are no tickers, don't bother. // If there are no tickers, don't bother.
alarm.wakeMeAt <- wakeTime alarm.wakeMeAt <- wakeTime
} else {
alarm.wakeTime = 0
} }
} }
prevTime = now prevTime = now
......
...@@ -34,3 +34,12 @@ func TestTicker(t *testing.T) { ...@@ -34,3 +34,12 @@ func TestTicker(t *testing.T) {
t.Fatalf("Ticker did not shut down") t.Fatalf("Ticker did not shut down")
} }
} }
// Test that a bug tearing down a ticker has been fixed. This routine should not deadlock.
func TestTeardown(t *testing.T) {
for i := 0; i < 3; i++ {
ticker := NewTicker(1e8)
<-ticker.C
ticker.Stop()
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment