mirror of
https://github.com/ipfs/kubo.git
synced 2026-03-03 23:38:07 +08:00
connect timing fixes to reuseport
This commit is contained in:
parent
7a3e0cdc75
commit
9062b9fe6c
2
Godeps/Godeps.json
generated
2
Godeps/Godeps.json
generated
@ -160,7 +160,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/jbenet/go-reuseport",
|
||||
"Rev": "f2ab96a83e1b33b66478eedd314884755d771933"
|
||||
"Rev": "1e1968c4744fef51234e83f015aa0187b4bd796b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/jbenet/go-sockaddr/net",
|
||||
|
||||
37
Godeps/_workspace/src/github.com/jbenet/go-reuseport/impl_unix.go
generated
vendored
37
Godeps/_workspace/src/github.com/jbenet/go-reuseport/impl_unix.go
generated
vendored
@ -106,18 +106,27 @@ func dial(dialer net.Dialer, netw, addr string) (c net.Conn, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if fd, err = socket(rfamily, socktype, rprotocol); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// look at dialTCP in http://golang.org/src/net/tcpsock_posix.go .... !
|
||||
// here we just try again 3 times.
|
||||
for i := 0; i < 3; i++ {
|
||||
if fd, err = socket(rfamily, socktype, rprotocol); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = syscall.Bind(fd, localSockaddr); err != nil {
|
||||
// fmt.Println("bind failed")
|
||||
syscall.Close(fd)
|
||||
return nil, err
|
||||
if err = syscall.Bind(fd, localSockaddr); err != nil {
|
||||
// fmt.Println("bind failed")
|
||||
syscall.Close(fd)
|
||||
return nil, err
|
||||
}
|
||||
if err = connect(fd, remoteSockaddr); err != nil {
|
||||
syscall.Close(fd)
|
||||
// fmt.Println("connect failed", localSockaddr, err)
|
||||
continue // try again.
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
if err = connect(fd, remoteSockaddr); err != nil {
|
||||
syscall.Close(fd)
|
||||
// fmt.Println("connect failed", localSockaddr, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -314,6 +323,7 @@ func connect(fd int, ra syscall.Sockaddr) error {
|
||||
}
|
||||
|
||||
var err error
|
||||
start := time.Now()
|
||||
for {
|
||||
// if err := fd.pd.WaitWrite(); err != nil {
|
||||
// return err
|
||||
@ -321,7 +331,8 @@ func connect(fd int, ra syscall.Sockaddr) error {
|
||||
// i'd use the above fd.pd.WaitWrite to poll io correctly, just like net sockets...
|
||||
// but of course, it uses fucking runtime_* functions that _cannot_ be used by
|
||||
// non-go-stdlib source... seriously guys, what kind of bullshit is that!?
|
||||
<-time.After(20 * time.Microsecond)
|
||||
// we're relegated to using syscall.Select (what nightmare that is) or using
|
||||
// a simple but totally bogus time-based wait. garbage.
|
||||
var nerr int
|
||||
nerr, err = syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_ERROR)
|
||||
if err != nil {
|
||||
@ -329,6 +340,10 @@ func connect(fd int, ra syscall.Sockaddr) error {
|
||||
}
|
||||
switch err = syscall.Errno(nerr); err {
|
||||
case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
|
||||
if time.Now().Sub(start) > time.Second {
|
||||
return err
|
||||
}
|
||||
<-time.After(20 * time.Microsecond)
|
||||
case syscall.Errno(0), syscall.EISCONN:
|
||||
return nil
|
||||
default:
|
||||
|
||||
8
Godeps/_workspace/src/github.com/jbenet/go-reuseport/interface.go
generated
vendored
8
Godeps/_workspace/src/github.com/jbenet/go-reuseport/interface.go
generated
vendored
@ -71,16 +71,16 @@ type Dialer struct {
|
||||
// Returns a net.Conn created from a file discriptor for a socket
|
||||
// with SO_REUSEPORT and SO_REUSEADDR option set.
|
||||
func (d *Dialer) Dial(network, address string) (net.Conn, error) {
|
||||
// there's a rare case where dial returns successfully but for some reason the
|
||||
// RemoteAddr is not yet set. We wait here a while until it is, and if too long
|
||||
// passes, we fail.
|
||||
c, err := dial(d.D, network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// there's a rare case where dial returns successfully but for some reason the
|
||||
// RemoteAddr is not yet set. We wait here a while until it is, and if too long
|
||||
// passes, we fail. This is horrendous.
|
||||
for start := time.Now(); c.RemoteAddr() == nil; {
|
||||
if time.Now().Sub(start) > time.Second {
|
||||
if time.Now().Sub(start) > (time.Millisecond * 500) {
|
||||
c.Close()
|
||||
return nil, ErrReuseFailed
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user