From 734d4637c5925826904ffe7406cd411568928cb4 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Thu, 6 Mar 2014 00:07:16 +1100 Subject: [PATCH] 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 --- src/pkg/net/fd_unix.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) 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 } -- 2.50.0