From efbb12ae8a4a9ea4b15b2929f9adc931c43b315b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 28 Mar 2011 18:35:53 +0000 Subject: [PATCH] re PR go/48312 (http, rpc, websocket tests hang on Solaris 2/x86) PR go/48312 Fix fd_select.go for changes in FD handling. We have to wake up the goroutine waiting in select each time we change the set of descriptors we are waiting for, unlike epoll. From-SVN: r171623 --- libgo/go/net/fd.go | 6 +++++- libgo/go/net/fd_linux.go | 6 +++--- libgo/go/net/fd_select.go | 13 ++++++++++--- libgo/go/net/newpollserver.go | 2 +- libgo/go/net/newpollserver_rtems.go | 2 +- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd.go index 7acee149e1f..c8440ae484a 100644 --- a/libgo/go/net/fd.go +++ b/libgo/go/net/fd.go @@ -122,9 +122,13 @@ func (s *pollServer) AddFD(fd *netFD, mode int) { 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 --git a/libgo/go/net/fd_linux.go b/libgo/go/net/fd_linux.go index 69fbc02c0c1..dcf65c014d5 100644 --- a/libgo/go/net/fd_linux.go +++ b/libgo/go/net/fd_linux.go @@ -47,7 +47,7 @@ func newpollster() (p *pollster, err os.Error) { 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 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error { 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 --git a/libgo/go/net/fd_select.go b/libgo/go/net/fd_select.go index 61759ca6ebc..e9c68ab2ccc 100644 --- a/libgo/go/net/fd_select.go +++ b/libgo/go/net/fd_select.go @@ -32,7 +32,9 @@ func newpollster() (p *pollster, err os.Error) { 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 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error { 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 @@ func (p *pollster) DelFD(fd int, mode int) { // 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 @@ func (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) { 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 --git a/libgo/go/net/newpollserver.go b/libgo/go/net/newpollserver.go index 820e70b46f3..fff54dba71f 100644 --- a/libgo/go/net/newpollserver.go +++ b/libgo/go/net/newpollserver.go @@ -31,7 +31,7 @@ func newPollServer() (s *pollServer, err os.Error) { 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 --git a/libgo/go/net/newpollserver_rtems.go b/libgo/go/net/newpollserver_rtems.go index 05cb71a54da..7933f09f194 100644 --- a/libgo/go/net/newpollserver_rtems.go +++ b/libgo/go/net/newpollserver_rtems.go @@ -68,7 +68,7 @@ func newPollServer() (s *pollServer, err os.Error) { 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 }