net: add socket system call hooks for testing

This change adds socket system call hooks to existing test cases for
simulating a bit complicated network conditions to help making timeout
and dual IP stack test cases work more properly in followup changes.

Also test cases print debugging information in non-short mode like the
following:

Leaked goroutines:
net.TestWriteTimeout.func2(0xc20802a5a0, 0xc20801d000, 0x1000, 0x1000, 0xc2081d2ae0)
	/go/src/net/timeout_test.go:170 +0x98
created by net.TestWriteTimeout
	/go/src/net/timeout_test.go:173 +0x745
net.runDatagramPacketConnServer(0xc2080730e0, 0x2bd270, 0x3, 0x2c1770, 0xb, 0xc2081d2ba0, 0xc2081d2c00)
	/go/src/net/server_test.go:398 +0x667
created by net.TestTimeoutUDP
	/go/src/net/timeout_test.go:247 +0xc9
	(snip)

Leaked sockets:
3: {Cookie:615726511685632 Err:<nil> SocketErr:0}
5: {Cookie:7934075906097152 Err:<nil> SocketErr:0}

Socket statistical information:
{Family:1 Type:805306370 Protocol:0 Opened:17 Accepted:0 Connected:5 Closed:17}
{Family:2 Type:805306369 Protocol:0 Opened:450 Accepted:234 Connected:279 Closed:636}
{Family:1 Type:805306369 Protocol:0 Opened:11 Accepted:5 Connected:5 Closed:16}
{Family:28 Type:805306369 Protocol:0 Opened:95 Accepted:22 Connected:16 Closed:116}
{Family:2 Type:805306370 Protocol:0 Opened:84 Accepted:0 Connected:34 Closed:83}
{Family:28 Type:805306370 Protocol:0 Opened:52 Accepted:0 Connected:4 Closed:52}

Change-Id: I0e84be59a0699bc31245c78e2249423459b8cdda
Reviewed-on: https://go-review.googlesource.com/6390
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index 40b78bd..2934634 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -219,18 +219,27 @@
 }
 
 func BenchmarkGoLookupIP(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	for i := 0; i < b.N; i++ {
 		goLookupIP("www.example.com")
 	}
 }
 
 func BenchmarkGoLookupIPNoSuchHost(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	for i := 0; i < b.N; i++ {
 		goLookupIP("some.nonexistent")
 	}
 }
 
 func BenchmarkGoLookupIPWithBrokenNameServer(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	onceLoadConfig.Do(loadDefaultConfig)
 	if cfg.dnserr != nil || cfg.dnsConfig == nil {
 		b.Fatalf("loadConfig failed: %v", cfg.dnserr)
diff --git a/src/net/dnsname_test.go b/src/net/dnsname_test.go
index 57dd25f..4fecf8d 100644
--- a/src/net/dnsname_test.go
+++ b/src/net/dnsname_test.go
@@ -69,6 +69,9 @@
 }
 
 func BenchmarkDNSNames(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	benchmarks := append(tests, []testCase{
 		{strings.Repeat("a", 63), true},
 		{strings.Repeat("a", 64), false},
diff --git a/src/net/fd_unix.go b/src/net/fd_unix.go
index 24e6c59..9e19761 100644
--- a/src/net/fd_unix.go
+++ b/src/net/fd_unix.go
@@ -72,7 +72,7 @@
 	// Do not need to call fd.writeLock here,
 	// because fd is not yet accessible to user,
 	// so no concurrent operations are possible.
-	switch err := syscall.Connect(fd.sysfd, ra); err {
+	switch err := connectFunc(fd.sysfd, ra); err {
 	case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
 	case nil, syscall.EISCONN:
 		if !deadline.IsZero() && deadline.Before(time.Now()) {
@@ -114,7 +114,7 @@
 		if err := fd.pd.WaitWrite(); err != nil {
 			return err
 		}
-		nerr, err := syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
+		nerr, err := getsockoptIntFunc(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
 		if err != nil {
 			return err
 		}
@@ -130,9 +130,9 @@
 
 func (fd *netFD) destroy() {
 	// Poller may want to unregister fd in readiness notification mechanism,
-	// so this must be executed before closesocket.
+	// so this must be executed before closeFunc.
 	fd.pd.Close()
-	closesocket(fd.sysfd)
+	closeFunc(fd.sysfd)
 	fd.sysfd = -1
 	runtime.SetFinalizer(fd, nil)
 }
@@ -417,7 +417,7 @@
 	}
 
 	if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
-		closesocket(s)
+		closeFunc(s)
 		return nil, err
 	}
 	if err = netfd.init(); err != nil {
@@ -492,7 +492,3 @@
 
 	return os.NewFile(uintptr(ns), fd.name()), nil
 }
-
-func closesocket(s int) error {
-	return syscall.Close(s)
-}
diff --git a/src/net/fd_windows.go b/src/net/fd_windows.go
index 995bc4a..d685883 100644
--- a/src/net/fd_windows.go
+++ b/src/net/fd_windows.go
@@ -69,10 +69,6 @@
 	}
 }
 
-func closesocket(s syscall.Handle) error {
-	return syscall.Closesocket(s)
-}
-
 func canUseConnectEx(net string) bool {
 	switch net {
 	case "udp", "udp4", "udp6", "ip", "ip4", "ip6":
@@ -336,7 +332,7 @@
 		defer fd.setWriteDeadline(noDeadline)
 	}
 	if !canUseConnectEx(fd.net) {
-		return syscall.Connect(fd.sysfd, ra)
+		return connectFunc(fd.sysfd, ra)
 	}
 	// ConnectEx windows API requires an unconnected, previously bound socket.
 	if la == nil {
@@ -356,7 +352,7 @@
 	o := &fd.wop
 	o.sa = ra
 	_, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
-		return syscall.ConnectEx(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
+		return connectExFunc(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
 	})
 	if err != nil {
 		return err
@@ -370,9 +366,9 @@
 		return
 	}
 	// Poller may want to unregister fd in readiness notification mechanism,
-	// so this must be executed before closesocket.
+	// so this must be executed before closeFunc.
 	fd.pd.Close()
-	closesocket(fd.sysfd)
+	closeFunc(fd.sysfd)
 	fd.sysfd = syscall.InvalidHandle
 	// no need for a finalizer anymore
 	runtime.SetFinalizer(fd, nil)
@@ -540,7 +536,7 @@
 	// Associate our new socket with IOCP.
 	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
 	if err != nil {
-		closesocket(s)
+		closeFunc(s)
 		return nil, &OpError{"accept", fd.net, fd.laddr, err}
 	}
 	if err := netfd.init(); err != nil {
diff --git a/src/net/file_unix.go b/src/net/file_unix.go
index 214a419..8d806a1 100644
--- a/src/net/file_unix.go
+++ b/src/net/file_unix.go
@@ -18,13 +18,13 @@
 	}
 
 	if err = syscall.SetNonblock(fd, true); err != nil {
-		closesocket(fd)
+		closeFunc(fd)
 		return nil, err
 	}
 
 	sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
 	if err != nil {
-		closesocket(fd)
+		closeFunc(fd)
 		return nil, os.NewSyscallError("getsockopt", err)
 	}
 
@@ -33,7 +33,7 @@
 	lsa, _ := syscall.Getsockname(fd)
 	switch lsa.(type) {
 	default:
-		closesocket(fd)
+		closeFunc(fd)
 		return nil, syscall.EINVAL
 	case *syscall.SockaddrInet4:
 		family = syscall.AF_INET
@@ -64,7 +64,7 @@
 
 	netfd, err := newFD(fd, family, sotype, laddr.Network())
 	if err != nil {
-		closesocket(fd)
+		closeFunc(fd)
 		return nil, err
 	}
 	if err := netfd.init(); err != nil {
diff --git a/src/net/hook_cloexec.go b/src/net/hook_cloexec.go
new file mode 100644
index 0000000..870f0d7
--- /dev/null
+++ b/src/net/hook_cloexec.go
@@ -0,0 +1,14 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd linux
+
+package net
+
+import "syscall"
+
+var (
+	// Placeholders for socket system calls.
+	accept4Func func(int, int) (int, syscall.Sockaddr, error) = syscall.Accept4
+)
diff --git a/src/net/hook_unix.go b/src/net/hook_unix.go
new file mode 100644
index 0000000..626d07f
--- /dev/null
+++ b/src/net/hook_unix.go
@@ -0,0 +1,18 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package net
+
+import "syscall"
+
+var (
+	// Placeholders for socket system calls.
+	socketFunc        func(int, int, int) (int, error)         = syscall.Socket
+	closeFunc         func(int) error                          = syscall.Close
+	connectFunc       func(int, syscall.Sockaddr) error        = syscall.Connect
+	acceptFunc        func(int) (int, syscall.Sockaddr, error) = syscall.Accept
+	getsockoptIntFunc func(int, int, int) (int, error)         = syscall.GetsockoptInt
+)
diff --git a/src/net/hook_windows.go b/src/net/hook_windows.go
new file mode 100644
index 0000000..2a6e5bf
--- /dev/null
+++ b/src/net/hook_windows.go
@@ -0,0 +1,15 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import "syscall"
+
+var (
+	// Placeholders for socket system calls.
+	socketFunc    func(int, int, int) (syscall.Handle, error)                                               = syscall.Socket
+	closeFunc     func(syscall.Handle) error                                                                = syscall.Closesocket
+	connectFunc   func(syscall.Handle, syscall.Sockaddr) error                                              = syscall.Connect
+	connectExFunc func(syscall.Handle, syscall.Sockaddr, *byte, uint32, *uint32, *syscall.Overlapped) error = syscall.ConnectEx
+)
diff --git a/src/net/interface_test.go b/src/net/interface_test.go
index 16217e7..666f11a 100644
--- a/src/net/interface_test.go
+++ b/src/net/interface_test.go
@@ -229,6 +229,9 @@
 }
 
 func BenchmarkInterfaces(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	for i := 0; i < b.N; i++ {
 		if _, err := Interfaces(); err != nil {
 			b.Fatal(err)
@@ -237,6 +240,9 @@
 }
 
 func BenchmarkInterfaceByIndex(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	ifi := loopbackInterface()
 	if ifi == nil {
 		b.Skip("loopback interface not found")
@@ -249,6 +255,9 @@
 }
 
 func BenchmarkInterfaceByName(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	ifi := loopbackInterface()
 	if ifi == nil {
 		b.Skip("loopback interface not found")
@@ -261,6 +270,9 @@
 }
 
 func BenchmarkInterfaceAddrs(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	for i := 0; i < b.N; i++ {
 		if _, err := InterfaceAddrs(); err != nil {
 			b.Fatal(err)
@@ -269,6 +281,9 @@
 }
 
 func BenchmarkInterfacesAndAddrs(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	ifi := loopbackInterface()
 	if ifi == nil {
 		b.Skip("loopback interface not found")
@@ -281,6 +296,9 @@
 }
 
 func BenchmarkInterfacesAndMulticastAddrs(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	ifi := loopbackInterface()
 	if ifi == nil {
 		b.Skip("loopback interface not found")
diff --git a/src/net/ip_test.go b/src/net/ip_test.go
index 604da39..e6f4e65 100644
--- a/src/net/ip_test.go
+++ b/src/net/ip_test.go
@@ -53,6 +53,9 @@
 }
 
 func BenchmarkParseIP(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	for i := 0; i < b.N; i++ {
 		for _, tt := range parseIPTests {
 			ParseIP(tt.in)
@@ -108,6 +111,9 @@
 }
 
 func BenchmarkIPString(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	for i := 0; i < b.N; i++ {
 		for _, tt := range ipStringTests {
 			if tt.in != nil {
@@ -158,6 +164,9 @@
 }
 
 func BenchmarkIPMaskString(b *testing.B) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	for i := 0; i < b.N; i++ {
 		for _, tt := range ipMaskStringTests {
 			tt.in.String()
diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go
index f9ebe40..7597a92 100644
--- a/src/net/ipsock_posix.go
+++ b/src/net/ipsock_posix.go
@@ -14,12 +14,12 @@
 )
 
 func probeIPv4Stack() bool {
-	s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
+	s, err := socketFunc(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
 	switch err {
 	case syscall.EAFNOSUPPORT, syscall.EPROTONOSUPPORT:
 		return false
 	case nil:
-		closesocket(s)
+		closeFunc(s)
 	}
 	return true
 }
@@ -50,11 +50,11 @@
 	}
 
 	for i := range probes {
-		s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
+		s, err := socketFunc(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
 		if err != nil {
 			continue
 		}
-		defer closesocket(s)
+		defer closeFunc(s)
 		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, probes[i].value)
 		sa, err := probes[i].laddr.sockaddr(syscall.AF_INET6)
 		if err != nil {
diff --git a/src/net/main_cloexec_test.go b/src/net/main_cloexec_test.go
new file mode 100644
index 0000000..7903819
--- /dev/null
+++ b/src/net/main_cloexec_test.go
@@ -0,0 +1,25 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd linux
+
+package net
+
+func init() {
+	extraTestHookInstallers = append(extraTestHookInstallers, installAccept4TestHook)
+	extraTestHookUninstallers = append(extraTestHookUninstallers, uninstallAccept4TestHook)
+}
+
+var (
+	// Placeholders for saving original socket system calls.
+	origAccept4 = accept4Func
+)
+
+func installAccept4TestHook() {
+	accept4Func = sw.Accept4
+}
+
+func uninstallAccept4TestHook() {
+	accept4Func = origAccept4
+}
diff --git a/src/net/main_plan9_test.go b/src/net/main_plan9_test.go
new file mode 100644
index 0000000..bbd47aa
--- /dev/null
+++ b/src/net/main_plan9_test.go
@@ -0,0 +1,11 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+func installTestHooks() {}
+
+func uninstallTestHooks() {}
+
+func forceCloseSockets() {}
diff --git a/src/net/main_test.go b/src/net/main_test.go
new file mode 100644
index 0000000..bc0f92e
--- /dev/null
+++ b/src/net/main_test.go
@@ -0,0 +1,89 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+	"fmt"
+	"net/internal/socktest"
+	"os"
+	"runtime"
+	"sort"
+	"strings"
+	"testing"
+)
+
+var sw socktest.Switch
+
+func TestMain(m *testing.M) {
+	installTestHooks()
+
+	st := m.Run()
+
+	if !testing.Short() {
+		printLeakedGoroutines()
+		printLeakedSockets()
+		printSocketStats()
+	}
+	forceCloseSockets()
+	uninstallTestHooks()
+	os.Exit(st)
+}
+
+func printLeakedGoroutines() {
+	gss := leakedGoroutines()
+	if len(gss) == 0 {
+		return
+	}
+	fmt.Fprintf(os.Stderr, "Leaked goroutines:\n")
+	for _, gs := range gss {
+		fmt.Fprintf(os.Stderr, "%v\n", gs)
+	}
+	fmt.Fprintf(os.Stderr, "\n")
+}
+
+// leakedGoroutines returns a list of remaining goroutins used in test
+// cases.
+func leakedGoroutines() []string {
+	var gss []string
+	b := make([]byte, 2<<20)
+	b = b[:runtime.Stack(b, true)]
+	for _, s := range strings.Split(string(b), "\n\n") {
+		ss := strings.SplitN(s, "\n", 2)
+		if len(ss) != 2 {
+			continue
+		}
+		stack := strings.TrimSpace(ss[1])
+		if !strings.Contains(stack, "created by net") {
+			continue
+		}
+		gss = append(gss, stack)
+	}
+	sort.Strings(gss)
+	return gss
+}
+
+func printLeakedSockets() {
+	sos := sw.Sockets()
+	if len(sos) == 0 {
+		return
+	}
+	fmt.Fprintf(os.Stderr, "Leaked sockets:\n")
+	for s, so := range sos {
+		fmt.Fprintf(os.Stderr, "%v: %+v\n", s, so)
+	}
+	fmt.Fprintf(os.Stderr, "\n")
+}
+
+func printSocketStats() {
+	sts := sw.Stats()
+	if len(sts) == 0 {
+		return
+	}
+	fmt.Fprintf(os.Stderr, "Socket statistical information:\n")
+	for _, st := range sts {
+		fmt.Fprintf(os.Stderr, "%+v\n", st)
+	}
+	fmt.Fprintf(os.Stderr, "\n")
+}
diff --git a/src/net/main_unix_test.go b/src/net/main_unix_test.go
new file mode 100644
index 0000000..637ac3d
--- /dev/null
+++ b/src/net/main_unix_test.go
@@ -0,0 +1,49 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package net
+
+var (
+	// Placeholders for saving original socket system calls.
+	origSocket        = socketFunc
+	origClose         = closeFunc
+	origConnect       = connectFunc
+	origAccept        = acceptFunc
+	origGetsockoptInt = getsockoptIntFunc
+
+	extraTestHookInstallers   []func()
+	extraTestHookUninstallers []func()
+)
+
+func installTestHooks() {
+	socketFunc = sw.Socket
+	closeFunc = sw.Close
+	connectFunc = sw.Connect
+	acceptFunc = sw.Accept
+	getsockoptIntFunc = sw.GetsockoptInt
+
+	for _, fn := range extraTestHookInstallers {
+		fn()
+	}
+}
+
+func uninstallTestHooks() {
+	socketFunc = origSocket
+	closeFunc = origClose
+	connectFunc = origConnect
+	acceptFunc = origAccept
+	getsockoptIntFunc = origGetsockoptInt
+
+	for _, fn := range extraTestHookUninstallers {
+		fn()
+	}
+}
+
+func forceCloseSockets() {
+	for s := range sw.Sockets() {
+		closeFunc(s)
+	}
+}
diff --git a/src/net/main_windows_test.go b/src/net/main_windows_test.go
new file mode 100644
index 0000000..03c3796
--- /dev/null
+++ b/src/net/main_windows_test.go
@@ -0,0 +1,33 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+var (
+	// Placeholders for saving original socket system calls.
+	origSocket      = socketFunc
+	origClosesocket = closeFunc
+	origConnect     = connectFunc
+	origConnectEx   = connectExFunc
+)
+
+func installTestHooks() {
+	socketFunc = sw.Socket
+	closeFunc = sw.Closesocket
+	connectFunc = sw.Connect
+	connectExFunc = sw.ConnectEx
+}
+
+func uninstallTestHooks() {
+	socketFunc = origSocket
+	closeFunc = origClosesocket
+	connectFunc = origConnect
+	connectExFunc = origConnectEx
+}
+
+func forceCloseSockets() {
+	for s := range sw.Sockets() {
+		closeFunc(s)
+	}
+}
diff --git a/src/net/sock_cloexec.go b/src/net/sock_cloexec.go
index dec8185..842d7d5 100644
--- a/src/net/sock_cloexec.go
+++ b/src/net/sock_cloexec.go
@@ -14,7 +14,7 @@
 // Wrapper around the socket system call that marks the returned file
 // descriptor as nonblocking and close-on-exec.
 func sysSocket(family, sotype, proto int) (int, error) {
-	s, err := syscall.Socket(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto)
+	s, err := socketFunc(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto)
 	// On Linux the SOCK_NONBLOCK and SOCK_CLOEXEC flags were
 	// introduced in 2.6.27 kernel and on FreeBSD both flags were
 	// introduced in 10 kernel. If we get an EINVAL error on Linux
@@ -26,7 +26,7 @@
 
 	// See ../syscall/exec_unix.go for description of ForkLock.
 	syscall.ForkLock.RLock()
-	s, err = syscall.Socket(family, sotype, proto)
+	s, err = socketFunc(family, sotype, proto)
 	if err == nil {
 		syscall.CloseOnExec(s)
 	}
@@ -35,7 +35,7 @@
 		return -1, err
 	}
 	if err = syscall.SetNonblock(s, true); err != nil {
-		syscall.Close(s)
+		closeFunc(s)
 		return -1, err
 	}
 	return s, nil
@@ -44,7 +44,7 @@
 // Wrapper around the accept system call that marks the returned file
 // descriptor as nonblocking and close-on-exec.
 func accept(s int) (int, syscall.Sockaddr, error) {
-	ns, sa, err := syscall.Accept4(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
+	ns, sa, err := accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
 	// On Linux the accept4 system call was introduced in 2.6.28
 	// kernel and on FreeBSD it was introduced in 10 kernel. If we
 	// get an ENOSYS error on both Linux and FreeBSD, or EINVAL
@@ -63,7 +63,7 @@
 	// because we have put fd.sysfd into non-blocking mode.
 	// However, a call to the File method will put it back into
 	// blocking mode. We can't take that risk, so no use of ForkLock here.
-	ns, sa, err = syscall.Accept(s)
+	ns, sa, err = acceptFunc(s)
 	if err == nil {
 		syscall.CloseOnExec(ns)
 	}
@@ -71,7 +71,7 @@
 		return -1, nil, err
 	}
 	if err = syscall.SetNonblock(ns, true); err != nil {
-		syscall.Close(ns)
+		closeFunc(ns)
 		return -1, nil, err
 	}
 	return ns, sa, nil
diff --git a/src/net/sock_posix.go b/src/net/sock_posix.go
index 3f956df..013944e 100644
--- a/src/net/sock_posix.go
+++ b/src/net/sock_posix.go
@@ -42,11 +42,11 @@
 		return nil, err
 	}
 	if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
-		closesocket(s)
+		closeFunc(s)
 		return nil, err
 	}
 	if fd, err = newFD(s, family, sotype, net); err != nil {
-		closesocket(s)
+		closeFunc(s)
 		return nil, err
 	}
 
diff --git a/src/net/sock_windows.go b/src/net/sock_windows.go
index 6ccde3a..591861f 100644
--- a/src/net/sock_windows.go
+++ b/src/net/sock_windows.go
@@ -12,10 +12,10 @@
 	return syscall.SOMAXCONN
 }
 
-func sysSocket(f, t, p int) (syscall.Handle, error) {
+func sysSocket(family, sotype, proto int) (syscall.Handle, error) {
 	// See ../syscall/exec_unix.go for description of ForkLock.
 	syscall.ForkLock.RLock()
-	s, err := syscall.Socket(f, t, p)
+	s, err := socketFunc(family, sotype, proto)
 	if err == nil {
 		syscall.CloseOnExec(s)
 	}
diff --git a/src/net/sys_cloexec.go b/src/net/sys_cloexec.go
index 898fb7c..5a631aa 100644
--- a/src/net/sys_cloexec.go
+++ b/src/net/sys_cloexec.go
@@ -16,7 +16,7 @@
 func sysSocket(family, sotype, proto int) (int, error) {
 	// See ../syscall/exec_unix.go for description of ForkLock.
 	syscall.ForkLock.RLock()
-	s, err := syscall.Socket(family, sotype, proto)
+	s, err := socketFunc(family, sotype, proto)
 	if err == nil {
 		syscall.CloseOnExec(s)
 	}
@@ -25,7 +25,7 @@
 		return -1, err
 	}
 	if err = syscall.SetNonblock(s, true); err != nil {
-		syscall.Close(s)
+		closeFunc(s)
 		return -1, err
 	}
 	return s, nil
@@ -39,7 +39,7 @@
 	// because we have put fd.sysfd into non-blocking mode.
 	// However, a call to the File method will put it back into
 	// blocking mode. We can't take that risk, so no use of ForkLock here.
-	ns, sa, err := syscall.Accept(s)
+	ns, sa, err := acceptFunc(s)
 	if err == nil {
 		syscall.CloseOnExec(ns)
 	}
@@ -47,7 +47,7 @@
 		return -1, nil, err
 	}
 	if err = syscall.SetNonblock(ns, true); err != nil {
-		syscall.Close(ns)
+		closeFunc(ns)
 		return -1, nil, err
 	}
 	return ns, sa, nil
diff --git a/src/net/tcp_test.go b/src/net/tcp_test.go
index f9a340d..434c9c6 100644
--- a/src/net/tcp_test.go
+++ b/src/net/tcp_test.go
@@ -59,6 +59,9 @@
 }
 
 func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
+	uninstallTestHooks()
+	defer installTestHooks()
+
 	const msgLen = 512
 	conns := b.N
 	numConcurrent := runtime.GOMAXPROCS(-1) * 2
@@ -172,6 +175,8 @@
 	// The benchmark stresses concurrent reading and writing to the same connection.
 	// Such pattern is used in net/http and net/rpc.
 
+	uninstallTestHooks()
+	defer installTestHooks()
 	b.StopTimer()
 
 	P := runtime.GOMAXPROCS(0)