net: fix possible runtime.PollDesc leak when connect or listen fails

Makes it possible to return the spent runtime.PollDesc to
runtime.pollcache descriptor pool when netFD.connect or
syscall.Listen fails.

Fixes #5219.

R=dvyukov, dave, bradfitz, adg
CC=golang-dev
https://golang.org/cl/8318044
This commit is contained in:
Mikio Hara 2013-04-09 12:41:58 +09:00
parent 4d5affd045
commit e13341edd1
4 changed files with 10 additions and 6 deletions

View File

@ -122,12 +122,16 @@ func (fd *netFD) incref(closing bool) error {
func (fd *netFD) decref() {
fd.sysmu.Lock()
fd.sysref--
if fd.closing && fd.sysref == 0 && fd.sysfile != nil {
if fd.closing && fd.sysref == 0 {
// Poller may want to unregister fd in readiness notification mechanism,
// so this must be executed before sysfile.Close().
fd.pd.Close()
fd.sysfile.Close()
fd.sysfile = nil
if fd.sysfile != nil {
fd.sysfile.Close()
fd.sysfile = nil
} else {
closesocket(fd.sysfd)
}
fd.sysfd = -1
}
fd.sysmu.Unlock()

View File

@ -58,7 +58,7 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
setWriteDeadline(fd, deadline)
}
if err = fd.connect(ursa); err != nil {
closesocket(s)
fd.Close()
return nil, err
}
fd.isConnected = true

View File

@ -288,7 +288,7 @@ func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
}
err = syscall.Listen(fd.sysfd, listenerBacklog)
if err != nil {
closesocket(fd.sysfd)
fd.Close()
return nil, &OpError{"listen", net, laddr, err}
}
return &TCPListener{fd}, nil

View File

@ -271,7 +271,7 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
}
err = syscall.Listen(fd.sysfd, listenerBacklog)
if err != nil {
closesocket(fd.sysfd)
fd.Close()
return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
}
return &UnixListener{fd, laddr.Name}, nil