From: Joel Sing Date: Wed, 5 Mar 2014 13:07:16 +0000 (+1100) Subject: net: fix non-blocking connect handling on dragonfly X-Git-Tag: go1.3beta1~476 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=734d4637c5925826904ffe7406cd411568928cb4;p=gostls13.git net: fix non-blocking connect handling on dragonfly Performing multiple connect system calls on a non-blocking socket under DragonFly BSD does not necessarily result in errors from earlier connect calls being returned, particularly if we are connecting to localhost. Instead, once netpoll tells us that the socket is ready, get the SO_ERROR socket option to see if the connection succeeded or failed. Fixes #7474 LGTM=mikioh.mikioh R=mikioh.mikioh CC=golang-codereviews https://golang.org/cl/69340044 --- diff --git a/src/pkg/net/fd_unix.go b/src/pkg/net/fd_unix.go index 54aeaeb198..9b0c6158c8 100644 --- a/src/pkg/net/fd_unix.go +++ b/src/pkg/net/fd_unix.go @@ -96,6 +96,28 @@ func (fd *netFD) connect(la, ra syscall.Sockaddr) error { if err = fd.pd.WaitWrite(); err != nil { return err } + + // Performing multiple connect system calls on a non-blocking + // socket under DragonFly BSD does not necessarily result in + // earlier errors being returned, particularly if we are + // connecting to localhost. Instead, once netpoll tells us that + // the socket is ready, get the SO_ERROR socket option to see + // if the connection succeeded or failed. See issue 7474 for + // further details. At some point we may want to consider + // doing the same on other Unixes. + if runtime.GOOS == "dragonfly" { + nerr, err := syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) + if err != nil { + return err + } + if nerr == 0 { + return nil + } + err = syscall.Errno(nerr) + if err != syscall.EINPROGRESS && err != syscall.EALREADY && err != syscall.EINTR { + return err + } + } } return nil }