]> Cypherpunks repositories - gostls13.git/commitdiff
time.Ticker: fix bug arising when all tickers are dead.
authorRob Pike <r@golang.org>
Wed, 17 Feb 2010 22:55:29 +0000 (09:55 +1100)
committerRob Pike <r@golang.org>
Wed, 17 Feb 2010 22:55:29 +0000 (09:55 +1100)
thanks to yglgogo for analysis.

Fixes #593.

R=rsc
CC=golang-dev
https://golang.org/cl/210044

src/pkg/time/tick.go
src/pkg/time/tick_test.go

index bbbc469618f6d64b39fac9a103faf977e9aba1e7..885a290bcfaf9afdd5a4b372368b8e9f4d524da0 100644 (file)
@@ -39,16 +39,23 @@ type alarmer struct {
 
 // Set alarm to go off at time ns, if not already set earlier.
 func (a *alarmer) set(ns int64) {
-       // If there's no wakeLoop or the next tick we expect is too late, start a new wakeLoop
-       if a.wakeMeAt == nil || a.wakeTime > ns {
-               // Stop previous wakeLoop.
-               if a.wakeMeAt != nil {
-                       a.wakeMeAt <- -1
-               }
+       switch {
+       case a.wakeTime > ns:
+               // Next tick we expect is too late; shut down the late runner
+               // and (after fallthrough) start a new wakeLoop.
+               a.wakeMeAt <- -1
+               fallthrough
+       case a.wakeMeAt == nil:
+               // There's no wakeLoop, start one.
                a.wakeMeAt = make(chan int64, 10)
                go wakeLoop(a.wakeMeAt, a.wakeUp)
+               fallthrough
+       case a.wakeTime == 0:
+               // Nobody else is waiting; it's just us.
                a.wakeTime = ns
                a.wakeMeAt <- ns
+       default:
+               // There's already someone scheduled.
        }
 }
 
@@ -141,6 +148,8 @@ func tickerLoop() {
                                // Please send wakeup at earliest required time.
                                // If there are no tickers, don't bother.
                                alarm.wakeMeAt <- wakeTime
+                       } else {
+                               alarm.wakeTime = 0
                        }
                }
                prevTime = now
index e15793aea334a2cf2aa3fb7451cb4b7d2b804790..d089a9b98ca1739e1524fd863ee5f1a9ac53a831 100644 (file)
@@ -34,3 +34,12 @@ func TestTicker(t *testing.T) {
                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()
+       }
+}