From addda5b96fc594325c3619cb28d4a776a1253faa Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 6 Jan 2022 13:19:09 -0800 Subject: [PATCH] wgengine/magicsock: fix watchdog timeout on Close when IPv6 not available The blockForeverConn was only using its sync.Cond one side. Looks like it was just forgotten. Fixes #3671 Change-Id: I4ed0191982cdd0bfd451f133139428a4fa48238c Signed-off-by: Brad Fitzpatrick --- wgengine/magicsock/magicsock.go | 1 + wgengine/magicsock/magicsock_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index ceece58c4..68aaf9604 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -3121,6 +3121,7 @@ func (c *blockForeverConn) Close() error { return net.ErrClosed } c.closed = true + c.cond.Broadcast() return nil } diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 5ae18de52..0db371a64 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -1763,3 +1763,27 @@ func (m *peerMap) validate() error { return nil } + +func TestBlockForeverConnUnblocks(t *testing.T) { + c := newBlockForeverConn() + done := make(chan error, 1) + go func() { + defer close(done) + _, _, err := c.ReadFrom(make([]byte, 1)) + done <- err + }() + time.Sleep(50 * time.Millisecond) // give ReadFrom time to get blocked + if err := c.Close(); err != nil { + t.Fatal(err) + } + timer := time.NewTimer(5 * time.Second) + defer timer.Stop() + select { + case err := <-done: + if err != net.ErrClosed { + t.Errorf("got %v; want net.ErrClosed", err) + } + case <-timer.C: + t.Fatal("timeout") + } +}