net: use closesocket api instead of CloseHandle on Windows

thanks to piotrnar for the original CL.
Fixes #1371.

R=rsc
CC=golang-dev
https://golang.org/cl/3834042
diff --git a/src/pkg/net/fd.go b/src/pkg/net/fd.go
index 5adaf1d..5ec9184 100644
--- a/src/pkg/net/fd.go
+++ b/src/pkg/net/fd.go
@@ -606,3 +606,7 @@
 
 	return os.NewFile(ns, fd.sysfile.Name()), nil
 }
+
+func closesocket(s int) (errno int) {
+	return syscall.Close(s)
+}
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index 64eed4a..72685d6 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -9,6 +9,7 @@
 	"sync"
 	"syscall"
 	"unsafe"
+	"runtime"
 )
 
 // BUG(brainman): The Windows implementation does not implement SetTimeout.
@@ -28,15 +29,14 @@
 	closing bool
 
 	// immutable until Close
-	sysfd   int
-	family  int
-	proto   int
-	sysfile *os.File
-	cr      chan *ioResult
-	cw      chan *ioResult
-	net     string
-	laddr   Addr
-	raddr   Addr
+	sysfd  int
+	family int
+	proto  int
+	cr     chan *ioResult
+	cw     chan *ioResult
+	net    string
+	laddr  Addr
+	raddr  Addr
 
 	// owned by client
 	rdeadline_delta int64
@@ -149,14 +149,7 @@
 		laddr:  laddr,
 		raddr:  raddr,
 	}
-	var ls, rs string
-	if laddr != nil {
-		ls = laddr.String()
-	}
-	if raddr != nil {
-		rs = raddr.String()
-	}
-	f.sysfile = os.NewFile(fd, net+":"+ls+"->"+rs)
+	runtime.SetFinalizer(f, (*netFD).Close)
 	return f, nil
 }
 
@@ -178,15 +171,16 @@
 		// can handle the extra OS processes.  Otherwise we'll need to
 		// use the pollserver for Close too.  Sigh.
 		syscall.SetNonblock(fd.sysfd, false)
-		fd.sysfile.Close()
-		fd.sysfile = nil
+		closesocket(fd.sysfd)
 		fd.sysfd = -1
+		// no need for a finalizer anymore
+		runtime.SetFinalizer(fd, nil)
 	}
 	fd.sysmu.Unlock()
 }
 
 func (fd *netFD) Close() os.Error {
-	if fd == nil || fd.sysfile == nil {
+	if fd == nil || fd.sysfd == -1 {
 		return os.EINVAL
 	}
 
@@ -213,7 +207,7 @@
 	defer fd.rio.Unlock()
 	fd.incref()
 	defer fd.decref()
-	if fd.sysfile == nil {
+	if fd.sysfd == -1 {
 		return 0, os.EINVAL
 	}
 	// Submit receive request.
@@ -253,7 +247,7 @@
 	defer fd.rio.Unlock()
 	fd.incref()
 	defer fd.decref()
-	if fd.sysfile == nil {
+	if fd.sysfd == -1 {
 		return 0, nil, os.EINVAL
 	}
 	// Submit receive request.
@@ -290,7 +284,7 @@
 	defer fd.wio.Unlock()
 	fd.incref()
 	defer fd.decref()
-	if fd.sysfile == nil {
+	if fd.sysfd == -1 {
 		return 0, os.EINVAL
 	}
 	// Submit send request.
@@ -326,7 +320,7 @@
 	defer fd.wio.Unlock()
 	fd.incref()
 	defer fd.decref()
-	if fd.sysfile == nil {
+	if fd.sysfd == -1 {
 		return 0, os.EINVAL
 	}
 	// Submit send request.
@@ -352,7 +346,7 @@
 }
 
 func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) {
-	if fd == nil || fd.sysfile == nil {
+	if fd == nil || fd.sysfd == -1 {
 		return nil, os.EINVAL
 	}
 	fd.incref()
@@ -387,21 +381,21 @@
 	case syscall.ERROR_IO_PENDING:
 		// IO started, and we have to wait for it's completion.
 	default:
-		syscall.Close(s)
+		closesocket(s)
 		return nil, &OpError{"AcceptEx", fd.net, fd.laddr, os.Errno(e)}
 	}
 
 	// Wait for peer connection.
 	r := <-pckt.c
 	if r.errno != 0 {
-		syscall.Close(s)
+		closesocket(s)
 		return nil, &OpError{"AcceptEx", fd.net, fd.laddr, os.Errno(r.errno)}
 	}
 
 	// Inherit properties of the listening socket.
 	e = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, fd.sysfd)
 	if e != 0 {
-		syscall.Close(s)
+		closesocket(s)
 		return nil, &OpError{"Setsockopt", fd.net, fd.laddr, os.Errno(r.errno)}
 	}
 
@@ -422,17 +416,14 @@
 		laddr:  laddr,
 		raddr:  raddr,
 	}
-	var ls, rs string
-	if laddr != nil {
-		ls = laddr.String()
-	}
-	if raddr != nil {
-		rs = raddr.String()
-	}
-	f.sysfile = os.NewFile(s, fd.net+":"+ls+"->"+rs)
+	runtime.SetFinalizer(f, (*netFD).Close)
 	return f, nil
 }
 
+func closesocket(s int) (errno int) {
+	return syscall.Closesocket(int32(s))
+}
+
 func init() {
 	var d syscall.WSAData
 	e := syscall.WSAStartup(uint32(0x101), &d)
diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go
index dd796bc..4ba6a55 100644
--- a/src/pkg/net/ipsock.go
+++ b/src/pkg/net/ipsock.go
@@ -24,7 +24,7 @@
 	}
 	fd, e := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
 	if fd >= 0 {
-		syscall.Close(fd)
+		closesocket(fd)
 	}
 	return e == 0
 }
diff --git a/src/pkg/net/sock.go b/src/pkg/net/sock.go
index 3e105ad..8ad3548 100644
--- a/src/pkg/net/sock.go
+++ b/src/pkg/net/sock.go
@@ -47,7 +47,7 @@
 	if la != nil {
 		e = syscall.Bind(s, la)
 		if e != 0 {
-			syscall.Close(s)
+			closesocket(s)
 			return nil, os.Errno(e)
 		}
 	}
@@ -55,7 +55,7 @@
 	if ra != nil {
 		e = syscall.Connect(s, ra)
 		if e != 0 {
-			syscall.Close(s)
+			closesocket(s)
 			return nil, os.Errno(e)
 		}
 	}
@@ -67,7 +67,7 @@
 
 	fd, err = newFD(s, f, p, net, laddr, raddr)
 	if err != nil {
-		syscall.Close(s)
+		closesocket(s)
 		return nil, err
 	}
 
diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go
index b0cb8f9..a4bca11 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/pkg/net/tcpsock.go
@@ -244,7 +244,7 @@
 	}
 	errno := syscall.Listen(fd.sysfd, listenBacklog())
 	if errno != 0 {
-		syscall.Close(fd.sysfd)
+		closesocket(fd.sysfd)
 		return nil, &OpError{"listen", "tcp", laddr, os.Errno(errno)}
 	}
 	l = new(TCPListener)
diff --git a/src/pkg/net/unixsock.go b/src/pkg/net/unixsock.go
index 1c15e5e..2521969 100644
--- a/src/pkg/net/unixsock.go
+++ b/src/pkg/net/unixsock.go
@@ -342,7 +342,7 @@
 	}
 	e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog());
 	if e1 != 0 {
-		syscall.Close(fd.sysfd)
+		closesocket(fd.sysfd)
 		return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Error: os.Errno(e1)}
 	}
 	return &UnixListener{fd, laddr.Name}, nil