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
diff --git a/src/pkg/net/fd_unix.go b/src/pkg/net/fd_unix.go
index f52c98a..c160fae 100644
--- a/src/pkg/net/fd_unix.go
+++ b/src/pkg/net/fd_unix.go
@@ -122,12 +122,16 @@
 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()
diff --git a/src/pkg/net/sock_posix.go b/src/pkg/net/sock_posix.go
index e2487c8..7e6a2c0 100644
--- a/src/pkg/net/sock_posix.go
+++ b/src/pkg/net/sock_posix.go
@@ -58,7 +58,7 @@
 			setWriteDeadline(fd, deadline)
 		}
 		if err = fd.connect(ursa); err != nil {
-			closesocket(s)
+			fd.Close()
 			return nil, err
 		}
 		fd.isConnected = true
diff --git a/src/pkg/net/tcpsock_posix.go b/src/pkg/net/tcpsock_posix.go
index 8133ca1..2224e6a 100644
--- a/src/pkg/net/tcpsock_posix.go
+++ b/src/pkg/net/tcpsock_posix.go
@@ -288,7 +288,7 @@
 	}
 	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
diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go
index 760d38f..6490cae 100644
--- a/src/pkg/net/unixsock_posix.go
+++ b/src/pkg/net/unixsock_posix.go
@@ -271,7 +271,7 @@
 	}
 	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