]> Cypherpunks repositories - gostls13.git/commitdiff
net: permit pollster DelFD to return whether to call Wakeup
authorIan Lance Taylor <iant@golang.org>
Thu, 7 Feb 2013 01:18:53 +0000 (17:18 -0800)
committerIan Lance Taylor <iant@golang.org>
Thu, 7 Feb 2013 01:18:53 +0000 (17:18 -0800)
This is necessary for systems that use select as the pollster,
such as Solaris (supported by gccgo).  It corresponds to the
bool returned by AddFD.  In general it's not clearly defined
what happens when a descriptor used in a select is closed, and
different systems behave differently.  Waking up the select
will cause the right thing to happen: the closed descriptor
will be dropped from the next iteration.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/7303056

src/pkg/net/fd_bsd.go
src/pkg/net/fd_darwin.go
src/pkg/net/fd_linux.go
src/pkg/net/fd_unix.go

index 4f5dd6e524af8b0606e2372eee2bab657e027d6b..8bb1ae53847a83aab2739e179df6ca89c7bf0e47 100644 (file)
@@ -33,6 +33,8 @@ func newpollster() (p *pollster, err error) {
        return p, nil
 }
 
+// First return value is whether the pollServer should be woken up.
+// This version always returns false.
 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
        // pollServer is locked.
 
@@ -64,7 +66,9 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
        return false, nil
 }
 
-func (p *pollster) DelFD(fd int, mode int) {
+// Return value is whether the pollServer should be woken up.
+// This version always returns false.
+func (p *pollster) DelFD(fd int, mode int) bool {
        // pollServer is locked.
 
        var kmode int
@@ -77,6 +81,7 @@ func (p *pollster) DelFD(fd int, mode int) {
        // 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) {
index 3dd33edc2055d679bd66db4dc7d1fce9e5649dd9..382465ba6674448f7bf0c3e6c2f508b2686a22a8 100644 (file)
@@ -32,6 +32,8 @@ func newpollster() (p *pollster, err error) {
        return p, nil
 }
 
+// First return value is whether the pollServer should be woken up.
+// This version always returns false.
 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
        // pollServer is locked.
 
@@ -65,7 +67,9 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
        return false, nil
 }
 
-func (p *pollster) DelFD(fd int, mode int) {
+// Return value is whether the pollServer should be woken up.
+// This version always returns false.
+func (p *pollster) DelFD(fd int, mode int) bool {
        // pollServer is locked.
 
        var kmode int
@@ -80,6 +84,7 @@ func (p *pollster) DelFD(fd int, mode int) {
        //      rather than waiting for real event
        syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE|syscall.EV_RECEIPT)
        syscall.Kevent(p.kq, p.kbuf[0:], p.kbuf[0:], nil)
+       return false
 }
 
 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
index 085e423072aa3c6d2912979b2295b87bdc8efc48..03679196d996d27550ed97503dc042932e878557 100644 (file)
@@ -51,6 +51,8 @@ func newpollster() (p *pollster, err error) {
        return p, nil
 }
 
+// First return value is whether the pollServer should be woken up.
+// This version always returns false.
 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
        // pollServer is locked.
 
@@ -114,7 +116,9 @@ func (p *pollster) StopWaiting(fd int, bits uint) {
        }
 }
 
-func (p *pollster) DelFD(fd int, mode int) {
+// Return value is whether the pollServer should be woken up.
+// This version always returns false.
+func (p *pollster) DelFD(fd int, mode int) bool {
        // pollServer is locked.
 
        if mode == 'r' {
@@ -133,6 +137,7 @@ func (p *pollster) DelFD(fd int, mode int) {
                        i++
                }
        }
+       return false
 }
 
 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
index e9d2e4165f135ebaf11dc36382283c48d136b355..a97674267c5634cd42cdff8f99937b50a22acdd1 100644 (file)
@@ -109,17 +109,24 @@ func (s *pollServer) AddFD(fd *netFD, mode int) error {
 // Evict evicts fd from the pending list, unblocking
 // any I/O running on fd.  The caller must have locked
 // pollserver.
-func (s *pollServer) Evict(fd *netFD) {
+// Return value is whether the pollServer should be woken up.
+func (s *pollServer) Evict(fd *netFD) bool {
+       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)
        }
+       return doWakeup
 }
 
 var wakeupbuf [1]byte
@@ -386,9 +393,12 @@ func (fd *netFD) Close() error {
        // the final decref will close fd.sysfd.  This should happen
        // fairly quickly, since all the I/O is non-blocking, and any
        // attempts to block in the pollserver will return errClosing.
-       fd.pollServer.Evict(fd)
+       doWakeup := fd.pollServer.Evict(fd)
        fd.pollServer.Unlock()
        fd.decref()
+       if doWakeup {
+               fd.pollServer.Wakeup()
+       }
        return nil
 }