time: fix timer stop Due to data structure corruption, some timers could not be removed. Fixes #2495. R=golang-dev, adg CC=golang-dev, mdbrown https://golang.org/cl/5437060
diff --git a/src/pkg/runtime/time.goc b/src/pkg/runtime/time.goc index 23ad1aa..ad9f3aa 100644 --- a/src/pkg/runtime/time.goc +++ b/src/pkg/runtime/time.goc
@@ -133,9 +133,16 @@ return false; } - timers.t[i] = timers.t[--timers.len]; - siftup(i); - siftdown(i); + timers.len--; + if(i == timers.len) { + timers.t[i] = nil; + } else { + timers.t[i] = timers.t[timers.len]; + timers.t[timers.len] = nil; + timers.t[i]->i = i; + siftup(i); + siftdown(i); + } runtime·unlock(&timers); return true; }
diff --git a/src/pkg/time/sleep_test.go b/src/pkg/time/sleep_test.go index 4c4a079..6fa2b69 100644 --- a/src/pkg/time/sleep_test.go +++ b/src/pkg/time/sleep_test.go
@@ -205,3 +205,19 @@ } return nil } + +func TestTimerStopStress(t *testing.T) { + if testing.Short() { + return + } + for i := 0; i < 100; i++ { + go func(i int) { + timer := AfterFunc(2e9, func() { + t.Fatalf("timer %d was not stopped", i) + }) + Sleep(1e9) + timer.Stop() + }(i) + } + Sleep(3e9) +}