ipv4: retry ENOBUFS errors in TestPacketConnConcurrentReadWriteUnicast

This change is sheer speculation based on the failures observed in
golang/go#37319.

(A deadlock in the test prevented us from seeing the actual failure
mode of golang/go#51342 up until CL 387915, and it isn't obvious to me
that we should wait for another failure before trying a likely — and
otherwise harmless — fix.)

This is a port of CL 376095 to the "ipv4" package.

Fixes golang/go#51342.
(Maybe.)

Change-Id: Idd6d2d785dbb0c98404f99bd98a3c4ddc11cb2cf
Reviewed-on: https://go-review.googlesource.com/c/net/+/387916
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Bryan C. Mills
2022-02-24 16:00:15 -05:00
committed by Bryan Mills
parent f80d34dcf0
commit 3bcbab3f74
3 changed files with 70 additions and 15 deletions

14
ipv4/errors_other_test.go Normal file
View File

@@ -0,0 +1,14 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !(aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris)
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
package ipv4_test
// isENOBUFS reports whether err is unix.ENOBUFS.
// (Always false on non-Unix platforms.)
func isENOBUFS(err error) bool {
return false
}

20
ipv4/errors_unix_test.go Normal file
View File

@@ -0,0 +1,20 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package ipv4_test
import (
"errors"
"golang.org/x/sys/unix"
)
// isENOBUFS reports whether err is unix.ENOBUFS.
// (Always false on non-Unix platforms.)
func isENOBUFS(err error) bool {
return errors.Is(err, unix.ENOBUFS)
}

View File

@@ -12,6 +12,7 @@ import (
"strings"
"sync"
"testing"
"time"
"golang.org/x/net/internal/iana"
"golang.org/x/net/ipv4"
@@ -450,12 +451,22 @@ func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn,
if err := p.SetControlMessage(cf, toggle); err != nil {
fatalf("%v", err)
}
n, err := p.WriteTo(data, &cm, dst)
if err != nil {
fatalf("%v", err)
}
if n != len(data) {
fatalf("got %d; want %d", n, len(data))
backoff := time.Millisecond
for {
n, err := p.WriteTo(data, &cm, dst)
if err != nil {
if n == 0 && isENOBUFS(err) {
time.Sleep(backoff)
backoff *= 2
continue
}
fatalf("%v", err)
}
if n != len(data) {
fatalf("got %d; want %d", n, len(data))
}
break
}
}
batchWriter := func(toggle bool) {
@@ -476,15 +487,25 @@ func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn,
Addr: dst,
},
}
n, err := p.WriteBatch(ms, 0)
if err != nil {
fatalf("%v", err)
}
if n != len(ms) {
fatalf("got %d; want %d", n, len(ms))
}
if ms[0].N != len(data) {
fatalf("got %d; want %d", ms[0].N, len(data))
backoff := time.Millisecond
for {
n, err := p.WriteBatch(ms, 0)
if err != nil {
if n == 0 && isENOBUFS(err) {
time.Sleep(backoff)
backoff *= 2
continue
}
fatalf("%v", err)
}
if n != len(ms) {
fatalf("got %d; want %d", n, len(ms))
}
if ms[0].N != len(data) {
fatalf("got %d; want %d", ms[0].N, len(data))
}
break
}
}