1
0
mirror of https://github.com/golang/go synced 2024-11-26 01:57:56 -07:00

runtime: fix network timers related crash

Fixes #6103.

R=golang-dev, alex.brainman
CC=golang-dev
https://golang.org/cl/12686045
This commit is contained in:
Dmitriy Vyukov 2013-08-13 12:55:57 +04:00
parent 1ee21701c7
commit 9707f269c1
2 changed files with 39 additions and 3 deletions

View File

@ -703,3 +703,36 @@ func TestProlongTimeout(t *testing.T) {
c.Write(buf[:]) c.Write(buf[:])
} }
} }
func TestDeadlineRace(t *testing.T) {
switch runtime.GOOS {
case "plan9":
t.Skipf("skipping test on %q", runtime.GOOS)
}
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
ln := newLocalListener(t)
defer ln.Close()
c, err := Dial("tcp", ln.Addr().String())
if err != nil {
t.Fatalf("Dial: %v", err)
}
defer c.Close()
done := make(chan bool)
go func() {
t := time.NewTicker(2 * time.Microsecond).C
for {
if err := c.SetDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
break
}
<-t
}
done <- true
}()
var buf [1]byte
for i := 0; i < 1024; i++ {
c.Read(buf[:]) // ignore possible timeout errors
}
c.Close()
<-done
}

View File

@ -113,10 +113,13 @@ func runtime_pollWait(pd *PollDesc, mode int) (err int) {
runtime·lock(pd); runtime·lock(pd);
err = checkerr(pd, mode); err = checkerr(pd, mode);
if(err == 0) { if(err == 0) {
if(!netpollblock(pd, mode)) { while(!netpollblock(pd, mode)) {
err = checkerr(pd, mode); err = checkerr(pd, mode);
if(err == 0) if(err != 0)
runtime·throw("runtime_pollWait: unblocked by ioready"); break;
// Can happen if timeout has fired and unblocked us,
// but before we had a chance to run, timeout has been reset.
// Pretend it has not happened and retry.
} }
} }
runtime·unlock(pd); runtime·unlock(pd);