]> Cypherpunks repositories - gostls13.git/commitdiff
net: make sure failed Dial returns nil Conn
authorRuss Cox <rsc@golang.org>
Fri, 18 Oct 2013 19:35:45 +0000 (15:35 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 18 Oct 2013 19:35:45 +0000 (15:35 -0400)
Fixes #6614.

R=golang-dev, bradfitz, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/14950045

src/pkg/net/dial.go
src/pkg/net/net_test.go

index fb47795d79f7c8396e43383ae087b675e37b4ef9..6304818bf14062c3bde0be0913d7a7bbbad4600a 100644 (file)
@@ -215,26 +215,30 @@ func dialMulti(net, addr string, la Addr, ras addrList, deadline time.Time) (Con
 
 // dialSingle attempts to establish and returns a single connection to
 // the destination address.
-func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (Conn, error) {
+func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
        if la != nil && la.Network() != ra.Network() {
                return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
        }
        switch ra := ra.(type) {
        case *TCPAddr:
                la, _ := la.(*TCPAddr)
-               return dialTCP(net, la, ra, deadline)
+               c, err = dialTCP(net, la, ra, deadline)
        case *UDPAddr:
                la, _ := la.(*UDPAddr)
-               return dialUDP(net, la, ra, deadline)
+               c, err = dialUDP(net, la, ra, deadline)
        case *IPAddr:
                la, _ := la.(*IPAddr)
-               return dialIP(net, la, ra, deadline)
+               c, err = dialIP(net, la, ra, deadline)
        case *UnixAddr:
                la, _ := la.(*UnixAddr)
-               return dialUnix(net, la, ra, deadline)
+               c, err = dialUnix(net, la, ra, deadline)
        default:
                return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: addr}}
        }
+       if err != nil {
+               return nil, err // c is non-nil interface containing nil pointer
+       }
+       return c, nil
 }
 
 // Listen announces on the local network address laddr.
@@ -246,14 +250,19 @@ func Listen(net, laddr string) (Listener, error) {
        if err != nil {
                return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
        }
+       var l Listener
        switch la := la.toAddr().(type) {
        case *TCPAddr:
-               return ListenTCP(net, la)
+               l, err = ListenTCP(net, la)
        case *UnixAddr:
-               return ListenUnix(net, la)
+               l, err = ListenUnix(net, la)
        default:
                return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
        }
+       if err != nil {
+               return nil, err // l is non-nil interface containing nil pointer
+       }
+       return l, nil
 }
 
 // ListenPacket announces on the local network address laddr.
@@ -265,14 +274,19 @@ func ListenPacket(net, laddr string) (PacketConn, error) {
        if err != nil {
                return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
        }
+       var l PacketConn
        switch la := la.toAddr().(type) {
        case *UDPAddr:
-               return ListenUDP(net, la)
+               l, err = ListenUDP(net, la)
        case *IPAddr:
-               return ListenIP(net, la)
+               l, err = ListenIP(net, la)
        case *UnixAddr:
-               return ListenUnixgram(net, la)
+               l, err = ListenUnixgram(net, la)
        default:
                return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
        }
+       if err != nil {
+               return nil, err // l is non-nil interface containing nil pointer
+       }
+       return l, nil
 }
index ee6cf0fcdd99e340feca36944be81f1fedb2cfb9..1320096df8ff4afd427d8f330835756c15aa77bb 100644 (file)
@@ -218,3 +218,41 @@ func TestTCPClose(t *testing.T) {
                t.Fatal(err)
        }
 }
+
+func TestErrorNil(t *testing.T) {
+       c, err := Dial("tcp", "127.0.0.1:65535")
+       if err == nil {
+               t.Fatal("Dial 127.0.0.1:65535 succeeded")
+       }
+       if c != nil {
+               t.Fatalf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
+       }
+
+       // Make Listen fail by relistening on the same address.
+       l, err := Listen("tcp", "127.0.0.1:0")
+       if err != nil {
+               t.Fatal("Listen 127.0.0.1:0: %v", err)
+       }
+       defer l.Close()
+       l1, err := Listen("tcp", l.Addr().String())
+       if err == nil {
+               t.Fatal("second Listen %v: %v", l.Addr(), err)
+       }
+       if l1 != nil {
+               t.Fatalf("Listen returned non-nil interface %T(%v) with err != nil", l1, l1)
+       }
+
+       // Make ListenPacket fail by relistening on the same address.
+       lp, err := ListenPacket("udp", "127.0.0.1:0")
+       if err != nil {
+               t.Fatal("Listen 127.0.0.1:0: %v", err)
+       }
+       defer lp.Close()
+       lp1, err := ListenPacket("udp", lp.LocalAddr().String())
+       if err == nil {
+               t.Fatal("second Listen %v: %v", lp.LocalAddr(), err)
+       }
+       if lp1 != nil {
+               t.Fatalf("ListenPacket returned non-nil interface %T(%v) with err != nil", lp1, lp1)
+       }
+}