]> Cypherpunks repositories - gostls13.git/commitdiff
document and partially fix a race
authorRuss Cox <rsc@golang.org>
Thu, 16 Apr 2009 02:01:48 +0000 (19:01 -0700)
committerRuss Cox <rsc@golang.org>
Thu, 16 Apr 2009 02:01:48 +0000 (19:01 -0700)
R=r
DELTA=24  (21 added, 0 deleted, 3 changed)
OCL=27527
CL=27527

src/lib/net/fd.go

index 6066bd5cd2d24ff05dde1c5f6c2c675bd66540a4..c098c20b20f9ef47bdead08cb8a1d10201363b85 100644 (file)
@@ -126,13 +126,34 @@ func newPollServer() (s *pollServer, err *os.Error) {
 }
 
 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;