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)