]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix timers crash
authorDmitriy Vyukov <dvyukov@google.com>
Mon, 14 Nov 2011 18:59:48 +0000 (21:59 +0300)
committerDmitriy Vyukov <dvyukov@google.com>
Mon, 14 Nov 2011 18:59:48 +0000 (21:59 +0300)
Timer callbacks occasionally crash
with "sched while holding locks" message.

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

src/pkg/runtime/time.goc
src/pkg/time/sleep_test.go

index 5904f887fe85926b766a6615467a5310e7e50557..23ad1aaef7ecb41c0d96cc71b88d9b82d1b62ac7 100644 (file)
@@ -149,6 +149,8 @@ timerproc(void)
 {
        int64 delta, now;
        Timer *t;
+       void (*f)(int64, Eface);
+       Eface arg;
 
        for(;;) {
                runtime·lock(&timers);
@@ -173,7 +175,11 @@ timerproc(void)
                                siftdown(0);
                                t->i = -1;  // mark as removed
                        }
-                       t->f(now, t->arg);
+                       f = t->f;
+                       arg = t->arg;
+                       runtime·unlock(&timers);
+                       f(now, arg);
+                       runtime·lock(&timers);
                }
                if(delta < 0) {
                        // No timers left - put goroutine to sleep.
index 029a6cca07865a76a06697a46b8ee5b443c02e6e..dae7dfe8fb21c52db2b2dd647d6d5631414dedb9 100644 (file)
@@ -7,7 +7,9 @@ package time_test
 import (
        "errors"
        "fmt"
+       "runtime"
        "sort"
+       "sync/atomic"
        "testing"
        . "time"
 )
@@ -47,6 +49,20 @@ func TestAfterFunc(t *testing.T) {
        <-c
 }
 
+func TestAfterStress(t *testing.T) {
+       stop := uint32(0)
+       go func() {
+               for atomic.LoadUint32(&stop) == 0 {
+                       runtime.GC()
+               }
+       }()
+       c := Tick(1)
+       for i := 0; i < 100; i++ {
+               <-c
+       }
+       atomic.StoreUint32(&stop, 1)
+}
+
 func BenchmarkAfterFunc(b *testing.B) {
        i := b.N
        c := make(chan bool)