Patchwork libgo patch committed: Fixes for select based pollster

login
register
mail settings
Submitter Ian Taylor
Date Feb. 6, 2013, 10:40 p.m.
Message ID <mcrfw1983sa.fsf@google.com>
Download mbox | patch
Permalink /patch/218786/
State New
Headers show

Comments

Ian Taylor - Feb. 6, 2013, 10:40 p.m.
On Solaris the libgo networking library uses select.  This patch
implements some fixes for that code.  The Close method is changed to
actually do something; this is mainly for testing purposes.  More
importantly, when a socket is closed, the select needs to be restarted
so that the callers see the close.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

Patch

diff -r fd46f2eb83d3 libgo/go/net/fd_bsd.go
--- a/libgo/go/net/fd_bsd.go	Tue Feb 05 15:57:40 2013 -0800
+++ b/libgo/go/net/fd_bsd.go	Wed Feb 06 14:36:13 2013 -0800
@@ -64,7 +64,7 @@ 
 	return false, nil
 }
 
-func (p *pollster) DelFD(fd int, mode int) {
+func (p *pollster) DelFD(fd int, mode int) bool {
 	// pollServer is locked.
 
 	var kmode int
@@ -77,6 +77,7 @@ 
 	// EV_DELETE - delete event from kqueue list
 	syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)
 	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
+	return false
 }
 
 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
diff -r fd46f2eb83d3 libgo/go/net/fd_linux.go
--- a/libgo/go/net/fd_linux.go	Tue Feb 05 15:57:40 2013 -0800
+++ b/libgo/go/net/fd_linux.go	Wed Feb 06 14:36:13 2013 -0800
@@ -114,7 +114,7 @@ 
 	}
 }
 
-func (p *pollster) DelFD(fd int, mode int) {
+func (p *pollster) DelFD(fd int, mode int) bool {
 	// pollServer is locked.
 
 	if mode == 'r' {
@@ -133,6 +133,7 @@ 
 			i++
 		}
 	}
+	return false
 }
 
 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
diff -r fd46f2eb83d3 libgo/go/net/fd_select.go
--- a/libgo/go/net/fd_select.go	Tue Feb 05 15:57:40 2013 -0800
+++ b/libgo/go/net/fd_select.go	Wed Feb 06 14:36:13 2013 -0800
@@ -7,6 +7,7 @@ 
 package net
 
 import (
+	"errors"
 	"os"
 	"syscall"
 )
@@ -17,6 +18,7 @@ 
 	readyReadFds, readyWriteFds  *syscall.FdSet
 	nReady                       int
 	lastFd                       int
+	closed                       bool
 }
 
 func newpollster() (p *pollster, err error) {
@@ -35,6 +37,10 @@ 
 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
 	// pollServer is locked.
 
+	if p.closed {
+		return false, errors.New("pollster closed")
+	}
+
 	if mode == 'r' {
 		syscall.FDSet(fd, p.readFds)
 	} else {
@@ -52,19 +58,23 @@ 
 	return true, nil
 }
 
-func (p *pollster) DelFD(fd int, mode int) {
+func (p *pollster) DelFD(fd int, mode int) bool {
 	// pollServer is locked.
 
+	if p.closed {
+		return false
+	}
+
 	if mode == 'r' {
 		if !syscall.FDIsSet(fd, p.readFds) {
 			print("Select unexpected fd=", fd, " for read\n")
-			return
+			return false
 		}
 		syscall.FDClr(fd, p.readFds)
 	} else {
 		if !syscall.FDIsSet(fd, p.writeFds) {
 			print("Select unexpected fd=", fd, " for write\n")
-			return
+			return false
 		}
 		syscall.FDClr(fd, p.writeFds)
 	}
@@ -73,6 +83,8 @@ 
 	syscall.FDClr(fd, p.repeatFds)
 
 	// We don't worry about maxFd here.
+
+	return true
 }
 
 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
@@ -89,6 +101,10 @@ 
 		var e error
 		var tmpReadFds, tmpWriteFds syscall.FdSet
 		for {
+			if p.closed {
+				return -1, 0, errors.New("pollster closed")
+			}
+
 			// Temporary syscall.FdSet's into which the values are copied
 			// because select mutates the values.
 			tmpReadFds = *p.readFds
@@ -161,5 +177,6 @@ 
 }
 
 func (p *pollster) Close() error {
+	p.closed = true
 	return nil
 }
diff -r fd46f2eb83d3 libgo/go/net/fd_unix.go
--- a/libgo/go/net/fd_unix.go	Tue Feb 05 15:57:40 2013 -0800
+++ b/libgo/go/net/fd_unix.go	Wed Feb 06 14:36:13 2013 -0800
@@ -110,16 +110,24 @@ 
 // any I/O running on fd.  The caller must have locked
 // pollserver.
 func (s *pollServer) Evict(fd *netFD) {
+	doWakeup := false
 	if s.pending[fd.sysfd<<1] == fd {
 		s.WakeFD(fd, 'r', errClosing)
-		s.poll.DelFD(fd.sysfd, 'r')
+		if s.poll.DelFD(fd.sysfd, 'r') {
+			doWakeup = true
+		}
 		delete(s.pending, fd.sysfd<<1)
 	}
 	if s.pending[fd.sysfd<<1|1] == fd {
 		s.WakeFD(fd, 'w', errClosing)
-		s.poll.DelFD(fd.sysfd, 'w')
+		if s.poll.DelFD(fd.sysfd, 'w') {
+			doWakeup = true
+		}
 		delete(s.pending, fd.sysfd<<1|1)
 	}
+	if doWakeup {
+		s.Wakeup()
+	}
 }
 
 var wakeupbuf [1]byte