This patch fixes fd_select.go for the changes in FD handling in the latest libgo update. The code in libgo now takes advantage of the fact that if you change the set of descriptors used by epoll, it is not necessary to wake up the thread waiting in epoll_wait. That is not true of select: if you change the set of descriptors, you do have to wake up the select. This patch implements that. Bootstrapped on x86_64-unknown-linux-gnu. Ran Go testsuite using fd_select.go instead of fd_linux.go. Committed to mainline. This fixes PR go/48312.
Ian
diff -r 056f7c9c13f8 libgo/go/net/fd.go --- a/libgo/go/net/fd.go Mon Mar 28 11:28:45 2011 -0700 +++ b/libgo/go/net/fd.go Mon Mar 28 11:30:46 2011 -0700 @@ -122,9 +122,13 @@ doWakeup = true } - if err := s.poll.AddFD(intfd, mode, false); err != nil { + wake, err := s.poll.AddFD(intfd, mode, false) + if err != nil { panic("pollServer AddFD " + err.String()) } + if wake { + doWakeup = true + } s.Unlock() diff -r 056f7c9c13f8 libgo/go/net/fd_linux.go --- a/libgo/go/net/fd_linux.go Mon Mar 28 11:28:45 2011 -0700 +++ b/libgo/go/net/fd_linux.go Mon Mar 28 11:30:46 2011 -0700 @@ -47,7 +47,7 @@ return p, nil } -func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error { +func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) { // pollServer is locked. var already bool @@ -69,10 +69,10 @@ op = syscall.EPOLL_CTL_ADD } if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != 0 { - return os.NewSyscallError("epoll_ctl", e) + return false, os.NewSyscallError("epoll_ctl", e) } p.events[fd] = p.ctlEvent.Events - return nil + return false, nil } func (p *pollster) StopWaiting(fd int, bits uint) { diff -r 056f7c9c13f8 libgo/go/net/fd_select.go --- a/libgo/go/net/fd_select.go Mon Mar 28 11:28:45 2011 -0700 +++ b/libgo/go/net/fd_select.go Mon Mar 28 11:30:46 2011 -0700 @@ -32,7 +32,9 @@ return p, nil } -func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error { +func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) { + // pollServer is locked. + if mode == 'r' { syscall.FDSet(fd, p.readFds) } else { @@ -47,10 +49,12 @@ p.maxFd = fd } - return nil + return true, nil } func (p *pollster) DelFD(fd int, mode int) { + // pollServer is locked. + if mode == 'r' { if !syscall.FDIsSet(fd, p.readFds) { print("Select unexpected fd=", fd, " for read\n") @@ -71,7 +75,7 @@ // We don't worry about maxFd here. } -func (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) { +func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) { if p.nReady == 0 { var timeout *syscall.Timeval var tv syscall.Timeval @@ -89,7 +93,10 @@ tmpReadFds = *p.readFds tmpWriteFds = *p.writeFds + s.Unlock() n, e = syscall.Select(p.maxFd + 1, &tmpReadFds, &tmpWriteFds, nil, timeout) + s.Lock() + if e != syscall.EINTR { break } diff -r 056f7c9c13f8 libgo/go/net/newpollserver.go --- a/libgo/go/net/newpollserver.go Mon Mar 28 11:28:45 2011 -0700 +++ b/libgo/go/net/newpollserver.go Mon Mar 28 11:30:46 2011 -0700 @@ -31,7 +31,7 @@ if s.poll, err = newpollster(); err != nil { goto Error } - if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil { + if _, err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil { s.poll.Close() goto Error } diff -r 056f7c9c13f8 libgo/go/net/newpollserver_rtems.go --- a/libgo/go/net/newpollserver_rtems.go Mon Mar 28 11:28:45 2011 -0700 +++ b/libgo/go/net/newpollserver_rtems.go Mon Mar 28 11:30:46 2011 -0700 @@ -68,7 +68,7 @@ if s.poll, err = newpollster(); err != nil { goto Error } - if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil { + if _, err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil { s.poll.Close() goto Error }