net: ignore EADDRINUSE errors when dialing to IPv4 from IPv6 on FreeBSD

The failure mode in #34264 appears to match
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=210726.

That bug was supposed to have been fixed in FreeBSD 12, but we're
still observing failures specifically for the 6-to-4 case on FreeBSD
12.2. It is not clear to me whether FreeBSD 13.0 is also affected.

For #34264

Change-Id: Iba7c7fc57676ae628b13c0b8fe43ddf2251c3637
Reviewed-on: https://go-review.googlesource.com/c/go/+/369157
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Trust: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Bryan C. Mills 2021-12-03 14:02:58 -05:00 committed by Bryan Mills
parent 13d15d147d
commit c473ca0877
2 changed files with 22 additions and 2 deletions

View file

@ -537,6 +537,9 @@ func TestDialerPartialDeadline(t *testing.T) {
}
}
// isEADDRINUSE reports whether err is syscall.EADDRINUSE.
var isEADDRINUSE = func(err error) bool { return false }
func TestDialerLocalAddr(t *testing.T) {
if !supportsIPv4() || !supportsIPv6() {
t.Skip("both IPv4 and IPv6 are required")
@ -592,7 +595,9 @@ func TestDialerLocalAddr(t *testing.T) {
{"tcp", "::1", &UnixAddr{}, &AddrError{Err: "some error"}},
}
issue34264Index := -1
if supportsIPv4map() {
issue34264Index = len(tests)
tests = append(tests, test{
"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, nil,
})
@ -627,7 +632,7 @@ func TestDialerLocalAddr(t *testing.T) {
}
}
for _, tt := range tests {
for i, tt := range tests {
d := &Dialer{LocalAddr: tt.laddr}
var addr string
ip := ParseIP(tt.raddr)
@ -639,8 +644,16 @@ func TestDialerLocalAddr(t *testing.T) {
}
c, err := d.Dial(tt.network, addr)
if err == nil && tt.error != nil || err != nil && tt.error == nil {
if i == issue34264Index && runtime.GOOS == "freebsd" && isEADDRINUSE(err) {
// https://golang.org/issue/34264: FreeBSD through at least version 12.2
// has been observed to fail with EADDRINUSE when dialing from an IPv6
// local address to an IPv4 remote address.
t.Logf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error)
t.Logf("(spurious EADDRINUSE ignored on freebsd: see https://golang.org/issue/34264)")
} else {
t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error)
}
}
if err != nil {
if perr := parseDialError(err); perr != nil {
t.Error(perr)

View file

@ -8,11 +8,18 @@ package net
import (
"context"
"errors"
"syscall"
"testing"
"time"
)
func init() {
isEADDRINUSE = func(err error) bool {
return errors.Is(err, syscall.EADDRINUSE)
}
}
// Issue 16523
func TestDialContextCancelRace(t *testing.T) {
oldConnectFunc := connectFunc