ipv6: shut down the PacketConn on failure in TestPacketConnConcurrentReadWriteUnicast

This avoids a deadlock (observed in golang/go#50455) that may
otherwise swallow the error logs from a failure, which may help us
better diagnose the underlying problem.

For golang/go#50455.

Change-Id: Id73bd9589ae23385a433da0b24840ef945601f63
Reviewed-on: https://go-review.googlesource.com/c/net/+/376094
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-01-06 16:20:44 -05:00
committed by Bryan Mills
parent 5b0dc2dfae
commit 8b8fc0806a

View File

@@ -356,8 +356,6 @@ func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
}
func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn, data []byte, dst net.Addr, batch bool) {
t.Helper()
ifi, _ := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
@@ -368,23 +366,37 @@ func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn,
t.Fatal(err)
}
var firstError sync.Once
fatalf := func(format string, args ...interface{}) {
// On the first error, close the PacketConn to unblock the remaining
// goroutines. Suppress any further errors, which may occur simply due to
// closing the PacketConn.
first := false
firstError.Do(func() {
first = true
p.Close()
})
if first {
t.Helper()
t.Errorf(format, args...)
}
runtime.Goexit()
}
var wg sync.WaitGroup
reader := func() {
defer wg.Done()
b := make([]byte, 128)
n, cm, _, err := p.ReadFrom(b)
if err != nil {
t.Error(err)
return
fatalf("%v", err)
}
if !bytes.Equal(b[:n], data) {
t.Errorf("got %#v; want %#v", b[:n], data)
return
fatalf("got %#v; want %#v", b[:n], data)
}
s := cm.String()
if strings.Contains(s, ",") {
t.Errorf("should be space-separated values: %s", s)
return
fatalf("should be space-separated values: %s", s)
}
}
batchReader := func() {
@@ -397,27 +409,22 @@ func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn,
}
n, err := p.ReadBatch(ms, 0)
if err != nil {
t.Error(err)
return
fatalf("%v", err)
}
if n != len(ms) {
t.Errorf("got %d; want %d", n, len(ms))
return
fatalf("got %d; want %d", n, len(ms))
}
var cm ipv6.ControlMessage
if err := cm.Parse(ms[0].OOB[:ms[0].NN]); err != nil {
t.Error(err)
return
fatalf("%v", err)
}
b := ms[0].Buffers[0][:ms[0].N]
if !bytes.Equal(b, data) {
t.Errorf("got %#v; want %#v", b, data)
return
fatalf("got %#v; want %#v", b, data)
}
s := cm.String()
if strings.Contains(s, ",") {
t.Errorf("should be space-separated values: %s", s)
return
fatalf("should be space-separated values: %s", s)
}
}
writer := func(toggle bool) {
@@ -431,17 +438,14 @@ func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn,
cm.IfIndex = ifi.Index
}
if err := p.SetControlMessage(cf, toggle); err != nil {
t.Error(err)
return
fatalf("%v", err)
}
n, err := p.WriteTo(data, &cm, dst)
if err != nil {
t.Error(err)
return
fatalf("%v", err)
}
if n != len(data) {
t.Errorf("got %d; want %d", n, len(data))
return
fatalf("got %d; want %d", n, len(data))
}
}
batchWriter := func(toggle bool) {
@@ -455,8 +459,7 @@ func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn,
cm.IfIndex = ifi.Index
}
if err := p.SetControlMessage(cf, toggle); err != nil {
t.Error(err)
return
fatalf("%v", err)
}
ms := []ipv6.Message{
{
@@ -467,16 +470,13 @@ func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn,
}
n, err := p.WriteBatch(ms, 0)
if err != nil {
t.Error(err)
return
fatalf("%v", err)
}
if n != len(ms) {
t.Errorf("got %d; want %d", n, len(ms))
return
fatalf("got %d; want %d", n, len(ms))
}
if ms[0].N != len(data) {
t.Errorf("got %d; want %d", ms[0].N, len(data))
return
fatalf("got %d; want %d", ms[0].N, len(data))
}
}