time: fix deadlock in Sleep(0)

See time/sleep_test.go for repro.

R=golang-dev, r, rsc
CC=golang-dev, patrick.allen.higgins
https://golang.org/cl/6250072
This commit is contained in:
Dmitriy Vyukov 2012-05-29 22:30:56 +04:00
parent 93fe8c0c93
commit a0efca84e6
2 changed files with 26 additions and 1 deletions

View 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;

View 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
}