"time"
)
+func toErrno(err error) (syscall.Errno, bool) {
+ operr, ok := err.(*OpError)
+ if !ok {
+ return 0, false
+ }
+ syserr, ok := operr.Err.(*os.SyscallError)
+ if !ok {
+ return 0, false
+ }
+ errno, ok := syserr.Err.(syscall.Errno)
+ if !ok {
+ return 0, false
+ }
+ return errno, true
+}
+
+// TestAcceptIgnoreSomeErrors tests that windows TCPListener.AcceptTCP
+// handles broken connections. It verifies that broken connections do
+// not affect future connections.
func TestAcceptIgnoreSomeErrors(t *testing.T) {
- recv := func(ln Listener) (string, error) {
+ recv := func(ln Listener, ignoreSomeReadErrors bool) (string, error) {
c, err := ln.Accept()
if err != nil {
// Display windows errno in error message.
- operr, ok := err.(*OpError)
- if !ok {
- return "", err
- }
- errno, ok := operr.Err.(syscall.Errno)
+ errno, ok := toErrno(err)
if !ok {
return "", err
}
b := make([]byte, 100)
n, err := c.Read(b)
- if err != nil && err != io.EOF {
- return "", err
+ if err == nil || err == io.EOF {
+ return string(b[:n]), nil
+ }
+ errno, ok := toErrno(err)
+ if ok && ignoreSomeReadErrors && (errno == syscall.ERROR_NETNAME_DELETED || errno == syscall.WSAECONNRESET) {
+ return "", nil
}
- return string(b[:n]), nil
+ return "", err
}
send := func(addr string, data string) error {
}()
// Receive first or second connection.
- s, err := recv(ln)
+ s, err := recv(ln, true)
if err != nil {
t.Fatalf("recv failed: %v", err)
}
switch s {
case "":
- // First connection data is received, lets get second connection data.
+ // First connection data is received, let's get second connection data.
case "abc":
// First connection is lost forever, but that is ok.
return
}
// Get second connection data.
- s, err = recv(ln)
+ s, err = recv(ln, false)
if err != nil {
t.Fatalf("recv failed: %v", err)
}