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
This commit is contained in:
Joel Sing 2014-03-06 00:07:16 +11:00
parent 9a7cd11bc8
commit 734d4637c5
1 changed files with 22 additions and 0 deletions

View File

@ -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
}