summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2010-06-30 13:14:46 -0700
committerIan Lance Taylor <iant@golang.org>2010-06-30 13:14:46 -0700
commit86db7627c60254c554107deff95dbc428a930e33 (patch)
tree6d971ec4784d9c080bec2fc01c9cf132750705c6
parentb04ac4bb6e0a81f737b22e301936dbbcf0f3b52b (diff)
downloadgo-86db7627c60254c554107deff95dbc428a930e33.tar.gz
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
-rw-r--r--src/pkg/io/pipe.go3
1 files changed, 2 insertions, 1 deletions
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