]> Cypherpunks repositories - gostls13.git/commitdiff
net: fix inconsistent error values on Read
authorMikio Hara <mikioh.mikioh@gmail.com>
Thu, 16 Apr 2015 14:10:56 +0000 (23:10 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Sat, 18 Apr 2015 02:19:46 +0000 (02:19 +0000)
This change fixes inconsistent error values on Read,
ReadFrom{,UDP,IP,Unix} and ReadMsg{UDP,IP,Unix}.

Updates #4856.

Change-Id: I7de5663094e09be2d78cdb18ce6f1e7ec260888d
Reviewed-on: https://go-review.googlesource.com/8992
Reviewed-by: Ian Lance Taylor <iant@golang.org>
17 files changed:
src/net/error_test.go
src/net/fd_unix.go
src/net/fd_windows.go
src/net/iprawsock_plan9.go
src/net/iprawsock_posix.go
src/net/net.go
src/net/net_test.go
src/net/sendfile_dragonfly.go
src/net/sendfile_freebsd.go
src/net/sendfile_linux.go
src/net/tcpsock_plan9.go
src/net/tcpsock_posix.go
src/net/timeout_test.go
src/net/udpsock_plan9.go
src/net/udpsock_posix.go
src/net/unixsock_plan9.go
src/net/unixsock_posix.go

index d7f502ef194c1b3f96797a902f160574b22daf7c..4b57d9e457ef3bdecd0543174f41741a1ecf260a 100644 (file)
@@ -6,6 +6,7 @@ package net
 
 import (
        "fmt"
+       "io"
        "net/internal/socktest"
        "os"
        "runtime"
@@ -248,3 +249,46 @@ func TestListenPacketError(t *testing.T) {
                }
        }
 }
+
+// parseReadError parses nestedErr and reports whether it is a valid
+// error value from Read functions.
+// It returns nil when nestedErr is valid.
+func parseReadError(nestedErr error) error {
+       if nestedErr == nil {
+               return nil
+       }
+
+       switch err := nestedErr.(type) {
+       case *OpError:
+               if err := err.isValid(); err != nil {
+                       return err
+               }
+               nestedErr = err.Err
+               goto second
+       }
+       if nestedErr == io.EOF {
+               return nil
+       }
+       return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
+
+second:
+       if isPlatformError(nestedErr) {
+               return nil
+       }
+       switch err := nestedErr.(type) {
+       case *os.SyscallError:
+               nestedErr = err.Err
+               goto third
+       }
+       switch nestedErr {
+       case errClosing, errTimeout:
+               return nil
+       }
+       return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
+
+third:
+       if isPlatformError(nestedErr) {
+               return nil
+       }
+       return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
+}
index 9e1976136dc911e232671af8121bfd57271d56eb..08c8568a809dc272a2090dcc0e422c56d5b2b143 100644 (file)
@@ -226,7 +226,7 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
        }
        defer fd.readUnlock()
        if err := fd.pd.PrepareRead(); err != nil {
-               return 0, &OpError{"read", fd.net, fd.raddr, err}
+               return 0, err
        }
        for {
                n, err = syscall.Read(int(fd.sysfd), p)
@@ -241,9 +241,6 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
                err = fd.eofError(n, err)
                break
        }
-       if err != nil && err != io.EOF {
-               err = &OpError{"read", fd.net, fd.raddr, err}
-       }
        return
 }
 
@@ -253,7 +250,7 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
        }
        defer fd.readUnlock()
        if err := fd.pd.PrepareRead(); err != nil {
-               return 0, nil, &OpError{"read", fd.net, fd.laddr, err}
+               return 0, nil, err
        }
        for {
                n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
@@ -268,9 +265,6 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
                err = fd.eofError(n, err)
                break
        }
-       if err != nil && err != io.EOF {
-               err = &OpError{"read", fd.net, fd.laddr, err}
-       }
        return
 }
 
@@ -280,7 +274,7 @@ func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
        }
        defer fd.readUnlock()
        if err := fd.pd.PrepareRead(); err != nil {
-               return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err}
+               return 0, 0, 0, nil, err
        }
        for {
                n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
@@ -295,9 +289,6 @@ func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
                err = fd.eofError(n, err)
                break
        }
-       if err != nil && err != io.EOF {
-               err = &OpError{"read", fd.net, fd.laddr, err}
-       }
        return
 }
 
index 3b771aacbcdd8cee001d05b17f4f3cd1fa456a0a..5bb048c1782a4663c9761cafaea981902ff4c828 100644 (file)
@@ -5,7 +5,6 @@
 package net
 
 import (
-       "io"
        "os"
        "runtime"
        "sync"
@@ -455,7 +454,7 @@ func (fd *netFD) closeWrite() error {
 
 func (fd *netFD) Read(buf []byte) (int, error) {
        if err := fd.readLock(); err != nil {
-               return 0, &OpError{Op: "read", Net: fd.net, Addr: fd.raddr, Err: err}
+               return 0, err
        }
        defer fd.readUnlock()
        o := &fd.rop
@@ -466,11 +465,7 @@ func (fd *netFD) Read(buf []byte) (int, error) {
        if raceenabled {
                raceAcquire(unsafe.Pointer(&ioSync))
        }
-       err = fd.eofError(n, err)
-       if err != nil && err != io.EOF {
-               err = &OpError{Op: "read", Net: fd.net, Addr: fd.raddr, Err: err}
-       }
-       return n, err
+       return n, fd.eofError(n, err)
 }
 
 func (fd *netFD) readFrom(buf []byte) (int, syscall.Sockaddr, error) {
@@ -478,7 +473,7 @@ func (fd *netFD) readFrom(buf []byte) (int, syscall.Sockaddr, error) {
                return 0, nil, nil
        }
        if err := fd.readLock(); err != nil {
-               return 0, nil, &OpError{Op: "read", Net: fd.net, Addr: fd.laddr, Err: err}
+               return 0, nil, err
        }
        defer fd.readUnlock()
        o := &fd.rop
@@ -490,12 +485,8 @@ func (fd *netFD) readFrom(buf []byte) (int, syscall.Sockaddr, error) {
                o.rsan = int32(unsafe.Sizeof(*o.rsa))
                return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
        })
-       err = fd.eofError(n, err)
-       if err != nil && err != io.EOF {
-               err = &OpError{Op: "read", Net: fd.net, Addr: fd.laddr, Err: err}
-       }
        sa, _ := o.rsa.Sockaddr()
-       return n, sa, err
+       return n, sa, fd.eofError(n, err)
 }
 
 func (fd *netFD) Write(buf []byte) (int, error) {
@@ -632,7 +623,7 @@ func (fd *netFD) dup() (*os.File, error) {
 }
 
 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
-       return 0, 0, 0, nil, &OpError{Op: "read", Net: fd.net, Addr: fd.laddr, Err: syscall.EWINDOWS}
+       return 0, 0, 0, nil, syscall.EWINDOWS
 }
 
 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
index e62d116b817c75d7f8406b197ad17bb8cbd22439..bdb0d9770f21be0a037d8f94045bc9a694792600 100644 (file)
@@ -23,12 +23,12 @@ type IPConn struct {
 // Timeout() == true after a fixed time limit; see SetDeadline and
 // SetReadDeadline.
 func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
-       return 0, nil, syscall.EPLAN9
+       return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // ReadFrom implements the PacketConn ReadFrom method.
 func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
-       return 0, nil, syscall.EPLAN9
+       return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // ReadMsgIP reads a packet from c, copying the payload into b and the
@@ -36,7 +36,7 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
 // bytes copied into b, the number of bytes copied into oob, the flags
 // that were set on the packet and the source address of the packet.
 func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
-       return 0, 0, 0, nil, syscall.EPLAN9
+       return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // WriteToIP writes an IP packet to addr via c, copying the payload
index 90955309233d7622f259ff459695d753f39f43fd..3c9d711b651d8861cfa875d262b1beea90992a69 100644 (file)
@@ -80,6 +80,9 @@ func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
        case *syscall.SockaddrInet6:
                addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
        }
+       if err != nil {
+               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+       }
        return n, addr, err
 }
 
@@ -126,6 +129,9 @@ func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err
        case *syscall.SockaddrInet6:
                addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
        }
+       if err != nil {
+               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+       }
        return
 }
 
index 439d21cfc1abc2913097de94a8eb8b060ac556b7..252a225f263d554ca5d8efe4c213b3317d416196 100644 (file)
@@ -121,7 +121,16 @@ func (c *conn) Read(b []byte) (int, error) {
        if !c.ok() {
                return 0, syscall.EINVAL
        }
-       return c.fd.Read(b)
+       n, err := c.fd.Read(b)
+       if err != nil && err != io.EOF {
+               err = &OpError{Op: "read", Net: c.fd.net, Err: err}
+               if c.fd.raddr != nil {
+                       err.(*OpError).Addr = c.fd.raddr
+               } else {
+                       err.(*OpError).Addr = c.fd.laddr // for unconnected-mode sockets
+               }
+       }
+       return n, err
 }
 
 // Write implements the Conn Write method.
index 5cdc769a51660ec6deb32aca4e87a4f2dbfc565d..df9373996fa0873318757940d5ccc7d38d14911a 100644 (file)
@@ -33,6 +33,9 @@ func TestShutdown(t *testing.T) {
                }
                var buf [10]byte
                n, err := c.Read(buf[:])
+               if perr := parseReadError(err); perr != nil {
+                       t.Error(perr)
+               }
                if n != 0 || err != io.EOF {
                        t.Errorf("server Read = %d, %v; want 0, io.EOF", n, err)
                        return
@@ -91,6 +94,9 @@ func TestShutdownUnix(t *testing.T) {
                }
                var buf [10]byte
                n, err := c.Read(buf[:])
+               if perr := parseReadError(err); perr != nil {
+                       t.Error(perr)
+               }
                if n != 0 || err != io.EOF {
                        t.Errorf("server Read = %d, %v; want 0, io.EOF", n, err)
                        return
@@ -166,6 +172,9 @@ func TestUDPListenClose(t *testing.T) {
        }()
        go func() {
                _, _, err = ln.ReadFrom(buf)
+               if perr := parseReadError(err); perr != nil {
+                       t.Error(perr)
+               }
                if err == nil {
                        t.Error("ReadFrom succeeded")
                } else {
index bc88fd3b907aa7fb7791f166ac065ce17ff6e637..a0025b6ab6cea8b0acd4e03e13afa4e65540e82a 100644 (file)
@@ -92,7 +92,7 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
                        // This includes syscall.ENOSYS (no kernel
                        // support) and syscall.EINVAL (fd types which
                        // don't implement sendfile together)
-                       err = &OpError{"sendfile", c.net, c.raddr, err1}
+                       err = err1
                        break
                }
        }
index ffc147262a8def15b616f2b57e8a31ab73c31bc1..a0324a328924c7c22548cd77dfaf24936a1f07b4 100644 (file)
@@ -92,7 +92,7 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
                        // This includes syscall.ENOSYS (no kernel
                        // support) and syscall.EINVAL (fd types which
                        // don't implement sendfile together)
-                       err = &OpError{"sendfile", c.net, c.raddr, err1}
+                       err = err1
                        break
                }
        }
index 5e117636a8076d3fe93f041407faa02d8cef8945..e76828d053ec0c28bdba967446998959e95329cf 100644 (file)
@@ -65,7 +65,7 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
                        // This includes syscall.ENOSYS (no kernel
                        // support) and syscall.EINVAL (fd types which
                        // don't implement sendfile together)
-                       err = &OpError{"sendfile", c.net, c.raddr, err1}
+                       err = err1
                        break
                }
        }
index ae2194277dfd38745ae2a38d61095a811fa726a4..2e646edf503b64bde497b475480d8a47710112d9 100644 (file)
@@ -23,7 +23,11 @@ func newTCPConn(fd *netFD) *TCPConn {
 
 // ReadFrom implements the io.ReaderFrom ReadFrom method.
 func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
-       return genericReadFrom(c, r)
+       n, err := genericReadFrom(c, r)
+       if err != nil && err != io.EOF {
+               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+       }
+       return n, err
 }
 
 // CloseRead shuts down the reading side of the TCP connection.
index 024dcd4f839e4bc78bdfdd0ddc1e8bd515cd39f0..91c8b0bdbb7eff35b110f9baa28cd2cfdbdb01ee 100644 (file)
@@ -60,9 +60,16 @@ func newTCPConn(fd *netFD) *TCPConn {
 // ReadFrom implements the io.ReaderFrom ReadFrom method.
 func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
        if n, err, handled := sendFile(c.fd, r); handled {
+               if err != nil && err != io.EOF {
+                       err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+               }
                return n, err
        }
-       return genericReadFrom(c, r)
+       n, err := genericReadFrom(c, r)
+       if err != nil && err != io.EOF {
+               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+       }
+       return n, err
 }
 
 // CloseRead shuts down the reading side of the TCP connection.
index 7e102c74d5cbb32a91e6f86a11930a7ed6abee63..7ccfef0cc5debe10a48e3b0d2e664ef750be521e 100644 (file)
@@ -138,16 +138,28 @@ func TestReadTimeout(t *testing.T) {
        if _, err = c.Read(buf); !isTimeoutError(err) {
                t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
        }
+       if perr := parseReadError(err); perr != nil {
+               t.Error(perr)
+       }
        if _, err = c.Read(buf); !isTimeoutError(err) {
                t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
        }
+       if perr := parseReadError(err); perr != nil {
+               t.Error(perr)
+       }
        c.SetDeadline(time.Now().Add(100 * time.Millisecond))
        if _, err = c.Read(buf); !isTimeoutError(err) {
                t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
        }
+       if perr := parseReadError(err); perr != nil {
+               t.Error(perr)
+       }
        if _, err = c.Read(buf); !isTimeoutError(err) {
                t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
        }
+       if perr := parseReadError(err); perr != nil {
+               t.Error(perr)
+       }
        c.SetReadDeadline(noDeadline)
        c.SetWriteDeadline(time.Now().Add(-1 * time.Second))
        errc := make(chan error)
@@ -164,15 +176,15 @@ func TestReadTimeout(t *testing.T) {
        c.Close()
        switch nerr := <-errc; err := nerr.(type) {
        case *OpError:
-               if err.Err != errClosing {
-                       t.Fatalf("Read: expected err %v, got %v", errClosing, err)
+               if perr := parseReadError(err); perr != nil {
+                       t.Error(perr)
                }
        default:
                if err == io.EOF && runtime.GOOS == "nacl" { // close enough; golang.org/issue/8044
                        break
                }
-               if err != errClosing {
-                       t.Fatalf("Read: expected err %v, got %v", errClosing, err)
+               if perr := parseReadError(err); perr != nil {
+                       t.Error(perr)
                }
        }
 }
@@ -618,6 +630,9 @@ func TestReadDeadlineDataAvailable(t *testing.T) {
        c.SetReadDeadline(time.Now().Add(-5 * time.Second)) // in the psat.
        buf := make([]byte, len(msg)/2)
        n, err := c.Read(buf)
+       if perr := parseReadError(err); perr != nil {
+               t.Error(perr)
+       }
        if n > 0 || !isTimeoutError(err) {
                t.Fatalf("client read = %d (%q) err=%v; want 0, timeout", n, buf[:n], err)
        }
index 269272632a73ceaaea8065a8e1f2f8e69995e396..ddaaa72093684a051d86fce8c732b7719398b4e5 100644 (file)
@@ -33,10 +33,10 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
        buf := make([]byte, udpHeaderSize+len(b))
        m, err := c.fd.data.Read(buf)
        if err != nil {
-               return
+               return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
        }
        if m < udpHeaderSize {
-               return 0, nil, errors.New("short read reading UDP header")
+               return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: errors.New("short read reading UDP header")}
        }
        buf = buf[:m]
 
@@ -59,7 +59,7 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
 // flags that were set on the packet and the source address of the
 // packet.
 func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
-       return 0, 0, 0, nil, syscall.EPLAN9
+       return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // WriteToUDP writes a UDP packet to addr via c, copying the payload
index 31ca8c04201d2c6b071725a14f6d6b1f7e89718f..05a11032ce36c8b7f2763d6b485a600b2634402c 100644 (file)
@@ -53,10 +53,11 @@ func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
 // ReadFromUDP can be made to time out and return an error with
 // Timeout() == true after a fixed time limit; see SetDeadline and
 // SetReadDeadline.
-func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
+func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error) {
        if !c.ok() {
                return 0, nil, syscall.EINVAL
        }
+       var addr *UDPAddr
        n, sa, err := c.fd.readFrom(b)
        switch sa := sa.(type) {
        case *syscall.SockaddrInet4:
@@ -64,7 +65,10 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
        case *syscall.SockaddrInet6:
                addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
        }
-       return
+       if err != nil {
+               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+       }
+       return n, addr, err
 }
 
 // ReadFrom implements the PacketConn ReadFrom method.
@@ -96,6 +100,9 @@ func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr,
        case *syscall.SockaddrInet6:
                addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
        }
+       if err != nil {
+               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+       }
        return
 }
 
index 64a511d6488b3c3d523d646b4fbe3f3d806b248b..a122a3dcbeed7999709a5d1ebb2506b72b8b62b6 100644 (file)
@@ -24,12 +24,12 @@ type UnixConn struct {
 // Timeout() == true after a fixed time limit; see SetDeadline and
 // SetReadDeadline.
 func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
-       return 0, nil, syscall.EPLAN9
+       return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // ReadFrom implements the PacketConn ReadFrom method.
 func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
-       return 0, nil, syscall.EPLAN9
+       return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // ReadMsgUnix reads a packet from c, copying the payload into b and
@@ -37,7 +37,7 @@ func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
 // bytes copied into b, the number of bytes copied into oob, the flags
 // that were set on the packet, and the source address of the packet.
 func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
-       return 0, 0, 0, nil, syscall.EPLAN9
+       return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // WriteToUnix writes a packet to addr via c, copying the payload from b.
index c5af8d34f3f8f9a55add47e531d92af7132335da..07b6134b48bcafb4081f46f362635fd4d850c212 100644 (file)
@@ -113,10 +113,11 @@ func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
 // ReadFromUnix can be made to time out and return an error with
 // Timeout() == true after a fixed time limit; see SetDeadline and
 // SetReadDeadline.
-func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
+func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
        if !c.ok() {
                return 0, nil, syscall.EINVAL
        }
+       var addr *UnixAddr
        n, sa, err := c.fd.readFrom(b)
        switch sa := sa.(type) {
        case *syscall.SockaddrUnix:
@@ -124,7 +125,10 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
                        addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
                }
        }
-       return
+       if err != nil {
+               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+       }
+       return n, addr, err
 }
 
 // ReadFrom implements the PacketConn ReadFrom method.
@@ -154,6 +158,9 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd
                        addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
                }
        }
+       if err != nil {
+               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+       }
        return
 }