]> Cypherpunks repositories - gostls13.git/commitdiff
time: fix deadlock in Sleep(0)
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 29 May 2012 18:30:56 +0000 (22:30 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Tue, 29 May 2012 18:30:56 +0000 (22:30 +0400)
See time/sleep_test.go for repro.

R=golang-dev, r, rsc
CC=golang-dev, patrick.allen.higgins
https://golang.org/cl/6250072

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

index a6b8352470030bf1379e16a9b1ed5b99f6701fc4..b18902f00fa94c0f8a72797c1dc97879ae1c68d7 100644 (file)
@@ -61,8 +61,11 @@ runtimeĀ·tsleep(int64 ns)
 {
        Timer t;
 
-       if(ns <= 0)
+       if(ns <= 0) {
+               g->status = Grunning;
+               g->waitreason = nil;
                return;
+       }
 
        t.when = runtimeĀ·nanotime() + ns;
        t.period = 0;
index 526d58d75e7a478781bf6e78cbf77ad134b31a48..e05773df6e1bc9607eaf723df281f351596ded82 100644 (file)
@@ -223,3 +223,25 @@ func TestTimerStopStress(t *testing.T) {
        }
        Sleep(3 * Second)
 }
+
+func TestSleepZeroDeadlock(t *testing.T) {
+       // Sleep(0) used to hang, the sequence of events was as follows.
+       // Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
+       // Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
+       // After the GC nobody wakes up the goroutine from Gwaiting status.
+       defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+       c := make(chan bool)
+       go func() {
+               for i := 0; i < 100; i++ {
+                       runtime.GC()
+               }
+               c <- true
+       }()
+       for i := 0; i < 100; i++ {
+               Sleep(0)
+               tmp := make(chan bool, 1)
+               tmp <- true
+               <-tmp
+       }
+       <-c
+}