From d364bb8ed786ab6c4877f19f0b286ed05894f0b0 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 30 Jun 2010 13:14:46 -0700 Subject: io: Avoid race condition in pipe. One goroutine started up and was waiting in rw. Then another goroutine decided to close the pipe. The closing goroutine stalled calling p.io.Lock() in pipeHalf.close. (This happened in gccgo). If the closing goroutine had been able to set the ioclosed flag, it would have gone on to tell the runner that the pipe was closed, which would then send an EINVAL to the goroutine sleeping in rw. Unlocking p.io before sleeping in rw avoids the race. R=rsc, rsc1 CC=golang-dev http://codereview.appspot.com/1682048 --- src/pkg/io/pipe.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pkg/io/pipe.go b/src/pkg/io/pipe.go index 79221bd49..898526921 100644 --- a/src/pkg/io/pipe.go +++ b/src/pkg/io/pipe.go @@ -144,10 +144,11 @@ func (p *pipeHalf) rw(data []byte) (n int, err os.Error) { // Run i/o operation. // Check ioclosed flag under lock to make sure we're still allowed to do i/o. p.io.Lock() - defer p.io.Unlock() if p.ioclosed { + p.io.Unlock() return 0, os.EINVAL } + p.io.Unlock() p.c1 <- data res := <-p.c2 return res.n, res.err -- cgit v1.2.3