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>
diff --git a/ipv6/readwrite_test.go b/ipv6/readwrite_test.go
index 260e7ee..9d1ed88 100644
--- a/ipv6/readwrite_test.go
+++ b/ipv6/readwrite_test.go
@@ -356,8 +356,6 @@
}
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
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))
}
}