From 285d0e3b4d04522553181602cdd97fb87d70c708 Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Thu, 6 May 2021 01:28:43 -0400 Subject: [PATCH] ipnlocal: fix deadlock in RequestEngineStatusAndWait() error path. If the engine was shutting down from a previous session (e.closing=true), it would return an error code when trying to get status. In that case, ipnlocal would never unblock any callers that were waiting on the status. Not sure if this ever happened in real life, but I accidentally triggered it while writing a test. Signed-off-by: Avery Pennarun --- ipn/ipnlocal/local.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 00065623a..dbd563adf 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -566,10 +566,18 @@ func (b *LocalBackend) findExitNodeIDLocked(nm *netmap.NetworkMap) (prefsChanged func (b *LocalBackend) setWgengineStatus(s *wgengine.Status, err error) { if err != nil { b.logf("wgengine status error: %v", err) + + b.statusLock.Lock() + b.statusChanged.Broadcast() + b.statusLock.Unlock() return } if s == nil { b.logf("[unexpected] non-error wgengine update with status=nil: %v", s) + + b.statusLock.Lock() + b.statusChanged.Broadcast() + b.statusLock.Unlock() return }