document and partially fix a race
R=r
DELTA=24 (21 added, 0 deleted, 3 changed)
OCL=27527
CL=27527
diff --git a/src/lib/net/fd.go b/src/lib/net/fd.go
index 6066bd5..c098c20 100644
--- a/src/lib/net/fd.go
+++ b/src/lib/net/fd.go
@@ -126,13 +126,34 @@
}
func (s *pollServer) AddFD(fd *netFD, mode int) {
- if err := s.poll.AddFD(fd.fd, mode, false); err != nil {
- panicln("pollServer AddFD ", fd.fd, ": ", err.String(), "\n");
+ // TODO(rsc): This check handles a race between
+ // one goroutine reading and another one closing,
+ // but it doesn't solve the race completely:
+ // it still could happen that one goroutine closes
+ // but we read fd.fd before it does, and then
+ // another goroutine creates a new open file with
+ // that fd, which we'd now be referring to.
+ // The fix is probably to send the Close call
+ // through the poll server too, except that
+ // not all Reads and Writes go through the poll
+ // server even now.
+ intfd := fd.fd;
+ if intfd < 0 {
+ // fd closed underfoot
+ if mode == 'r' {
+ fd.cr <- fd
+ } else {
+ fd.cw <- fd
+ }
+ return
+ }
+ if err := s.poll.AddFD(intfd, mode, false); err != nil {
+ panicln("pollServer AddFD ", intfd, ": ", err.String(), "\n");
return
}
var t int64;
- key := fd.fd << 1;
+ key := intfd << 1;
if mode == 'r' {
fd.ncr++;
t = fd.rdeadline;