1
0
mirror of https://github.com/golang/go synced 2024-11-27 01:51:23 -07:00

net: permit pollster DelFD to return whether to call Wakeup

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
This commit is contained in:
Ian Lance Taylor 2013-02-06 17:18:53 -08:00
parent c2fb6e2c0b
commit 0592c44956
4 changed files with 32 additions and 7 deletions

View 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) {

View 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) {

View 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) {

View 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
}