mirror of
https://github.com/golang/go
synced 2024-11-23 05:40:04 -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:
parent
c2fb6e2c0b
commit
0592c44956
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user